ziputil

package
v0.1.8 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 25, 2026 License: Apache-2.0 Imports: 10 Imported by: 0

Documentation

Overview

Package ziputil validates and safely reads ZIP archives used by evidence packs. Invariants: entry paths are validated, zip-bomb ratios are bounded, and unsafe collisions are rejected.

Index

Constants

View Source
const (
	// Path validation constants per spec Section 2.3.
	MaxPathLength    = 240 // Maximum total path length in bytes
	MaxSegmentLength = 80  // Maximum segment length in bytes (accommodates attestation filenames)

	// DefaultMaxCompressionRatio is the default maximum compression ratio allowed.
	// A ratio of 100 means the uncompressed size can be at most 100x the compressed size.
	// This helps prevent zip bomb attacks.
	DefaultMaxCompressionRatio = 100
)

Variables

This section is empty.

Functions

func CheckCompressionRatio

func CheckCompressionRatio(archive *zip.Reader, maxRatio int) error

CheckCompressionRatio rejects archives containing entries whose uncompressed-to-compressed ratio exceeds maxRatio. If maxRatio <= 0, DefaultMaxCompressionRatio is used.

func IsAppleDoubleFile

func IsAppleDoubleFile(path string) bool

IsAppleDoubleFile checks if a path is an AppleDouble metadata file. Per spec Section 7.3 (R-101), these SHOULD be rejected: - Files under __MACOSX/ directory (resource fork storage) - Files starting with ._ (AppleDouble sidecar files)

func ValidateDirectoryEntry

func ValidateDirectoryEntry(f *zip.File) error

ValidateDirectoryEntry checks that a ZIP entry's attributes are consistent with its path. Per spec Section 2.3 (R-321 through R-323, R-347): - A trailing "/" in the path indicates a directory entry - Directory entries MUST have size 0 - ZIP mode bits indicating directory MUST match path ending with "/" - ZIP mode bits indicating file MUST NOT have path ending with "/"

func ValidateNotAppleDouble

func ValidateNotAppleDouble(path string) error

ValidateNotAppleDouble rejects AppleDouble metadata files. Per spec Section 7.3 (R-101), these SHOULD be rejected as they: - Contain macOS-specific metadata not relevant to evidence packs - May contain unexpected executable content - Cause confusion when packs are created on macOS and consumed elsewhere

func ValidateNotDeviceFile

func ValidateNotDeviceFile(f *zip.File) error

ValidateNotDeviceFile checks that a ZIP entry is not a device file. Device files in ZIP archives are a security risk.

func ValidateNotSymlink(f *zip.File) error

ValidateNotSymlink checks that a ZIP entry is not a symlink. Symlinks in ZIP archives are a security risk as they can escape the extraction directory.

func ValidatePath

func ValidatePath(name string) error

ValidatePath checks that a zip entry path is safe per spec Section 2.3. It rejects: - Empty paths - Control characters - Backslashes (must use forward slashes only) - Trailing slashes (files must not end with /) - Empty segments (consecutive slashes like //) - Path traversal (. and .. segments) - Absolute paths (leading / or Windows drive letters) - Windows reserved characters (colons) - Windows reserved names (CON, PRN, etc. without extensions) - UNC paths (//server/share) - Non-NFC Unicode (path must equal its NFC normalization) - Paths exceeding length limits

func WindowsCanonicalPath

func WindowsCanonicalPath(path string) string

WindowsCanonicalPath returns the Windows-canonical form of a path for collision detection. On Windows, paths are case-insensitive and certain characters are stripped: - Trailing dots are stripped from each segment - Trailing spaces are stripped from each segment - Case is normalized to lowercase

Two paths that produce the same canonical form will collide on Windows. Use for duplicate detection in manifests.

Types

type SafeReader

type SafeReader struct {
	*zip.Reader
	// contains filtered or unexported fields
}

SafeReader wraps a zip.Reader with pre-validated security checks. All entries are validated at construction time, ensuring that iteration over the reader's files is safe.

SECURITY: SafeReader provides defense-in-depth by validating: - Compression ratio limits (zip bomb prevention) - Path safety (traversal, reserved names, encoding) - Entry count limits (DoS prevention) - Windows path collision detection

Use NewSafeReader to create validated instances. Direct construction bypasses validation and should be avoided.

func NewSafeReader

func NewSafeReader(r io.ReaderAt, size int64, opts ...SafeReaderOption) (*SafeReader, error)

NewSafeReader creates a SafeReader from an io.ReaderAt with comprehensive validation. Returns an error if any security check fails: - Entry count exceeds limits - Compression ratio exceeds limits (zip bomb detection) - Any path fails validation (traversal, encoding, reserved names) - Windows path collisions detected

Once created, iteration over r.File is guaranteed safe.

func NewSafeReaderFromZip

func NewSafeReaderFromZip(zr *zip.Reader, opts ...SafeReaderOption) (*SafeReader, error)

NewSafeReaderFromZip wraps an existing zip.Reader with validation. Use this when you already have a zip.Reader (e.g., from zip.OpenReader).

func (*SafeReader) FileNames

func (sr *SafeReader) FileNames() []string

FileNames returns a list of all file names in the archive (excluding directories).

func (*SafeReader) IsValidated

func (sr *SafeReader) IsValidated() bool

IsValidated returns true if the reader passed all security checks. This should always be true for readers created via NewSafeReader.

func (*SafeReader) OpenFile

func (sr *SafeReader) OpenFile(name string) (io.ReadCloser, error)

OpenFile opens a file from the archive by name. Returns an error if the file is not found.

type SafeReaderOption

type SafeReaderOption func(*safeReaderConfig)

SafeReaderOption configures SafeReader behavior.

func WithMaxCompressionRatio

func WithMaxCompressionRatio(ratio int) SafeReaderOption

WithMaxCompressionRatio sets a custom maximum compression ratio. Default is limits.MaxCompressionRatio (100:1).

func WithMaxEntries

func WithMaxEntries(max int) SafeReaderOption

WithMaxEntries sets a custom maximum entry count. Default is limits.MaxZipEntries.

func WithSkipCollisionCheck

func WithSkipCollisionCheck() SafeReaderOption

WithSkipCollisionCheck disables Windows path collision checking. Only use this for archives known to be safe or in test scenarios.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL