archive

package
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Oct 12, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package archive unpacks archives safely. Iron rule 7: path traversal, absolute paths, and symlinks that escape the destination directory are all refused.

Index

Constants

View Source
const MaxTotalBytes = 2 << 30 // 2 GiB

MaxTotalBytes caps the total extracted size. This is the zip bomb defence.

Variables

View Source
var (
	ErrTraversal   = errors.New("archive: path escapes the destination directory")
	ErrUnsupported = errors.New("archive: unsupported archive format")
	ErrTooLarge    = errors.New("archive: extracted size exceeds the limit")
)

Functions

func Decompress

func Decompress(src, name, dst string) error

Decompress writes the single file inside src to dst.

The output is capped at MaxTotalBytes exactly as extraction is. A single compressed file is the easiest decompression bomb there is -- bzip2 reaches ratios in the thousands, so a few hundred kilobytes downloaded and checksummed can fill a disk. The cap has to be on bytes WRITTEN, never on any length the file claims about itself. Decompress writes the single file inside src to dst. name is the original asset name -- src is the cache path, which is a bare sha256 with no suffix to read.

func Extract

func Extract(src, destDir string) ([]string, error)

Extract unpacks src into destDir, which must already exist. It guarantees:

  • every member's final path, after filepath.Clean, still sits inside destDir, otherwise ErrTraversal
  • absolute member paths are refused
  • symlinks: if the target resolves outside destDir, the whole archive is refused
  • contentless irregular members (device nodes, FIFOs, sockets) are skipped; an unknown type that declares content is refused
  • passing MaxTotalBytes aborts the extraction and cleans up

If the extracted tree turns out to be EXACTLY ONE top-level entry AND that entry is a directory, that layer is stripped (see stripTopDir). The relative paths returned are the stripped ones.

func IsArchive

func IsArchive(name string) bool

IsArchive reports whether a name looks like an archive we know. Known: .tar.gz .tgz .tar.xz (recognised, not unpacked - Extract returns ErrUnsupported) .tar .zip Anything else, a bare binary for instance, is false: the caller should install it as a single file.

func SingleFileCompression

func SingleFileCompression(name string) string

SingleFileCompression reports the compression on a single compressed file -- not a container, one file squeezed. restic ships `restic_0.19.1_linux_amd64.bz2` and nothing else for linux/amd64, and several projects ship a bare `.gz` the same way.

Returns "" for a tarball: `.tar.gz` is a container and goes through Extract.

Judged on the NAME, so callers pass the original asset name: a downloaded file sits in the cache under its sha256 and carries no suffix at all.

Types

This section is empty.

Jump to

Keyboard shortcuts

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