safearchive

package
v0.0.0-...-72daab1 Latest Latest
Warning

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

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

Documentation

Overview

Package safearchive implements bounded, fail-closed archive extraction for every remotely acquired artifact in FreeIran (protocol-core releases, provider binaries, any future archive).

v0.9.8.6 security contract — every extraction enforces:

  • a maximum ARCHIVE size (the on-disk staged file is checked before a single byte is unpacked);
  • a maximum TOTAL extracted byte budget (zip-bomb defence: a 100-byte archive must not be able to exhaust the disk);
  • a maximum INDIVIDUAL file size;
  • a maximum FILE COUNT;
  • path-traversal protection (zip-slip / tar-slip: every entry must resolve strictly inside the destination);
  • absolute-path rejection (POSIX "/abs" and Windows "C:\abs", "\\abs" and drive-relative forms);
  • symlink / hardlink entry rejection — a remotely acquired executable archive never needs links, and following attacker-controlled link targets is unacceptable. Other non-regular entries (devices, fifos) are rejected as well: malformed/hostile archives fail CLOSED, they never extract partially and report success.

v0.9.11 hardening: the sanitizer is HOST-INDEPENDENT. Archive entry names are validated in ARCHIVE space — lexically, with '/' as the only separator — BEFORE any host path conversion. The pre-0.9.11 sanitizer ran the host's filepath.Clean() over the raw name first: on Windows that translated "/" into "\" (so a POSIX-absolute entry such as "/etc/passwd-clone" became backslash-rooted and slipped past the absolute-entry test, only to be saved — or not — by the last-resort containment check), and the whole contract silently depended on host path semantics. The sanitized result must be IDENTICAL on every platform; the final containment decision is made with an OS-aware filepath.Rel check (case-insensitive on Windows) after the lexical gate.

Supported formats: .zip, .tar, .tar.gz/.tgz, .gz (single-file gzip of one executable, as published by MetaCubeX Mihomo for Linux), with content sniffing (PK / gzip magic) for misnamed staged files — mirroring the historical engine/coremgr behaviour.

A .gz whose decompressed stream is NOT a valid tar archive is treated as a single-file gzip: the staged output file takes the archive's base name with the .gz suffix stripped (e.g. "mihomo-linux-amd64-v1.18.x.gz" → "mihomo-linux-amd64-v1.18.x"). Callers that look up the executable by walking the unpacked directory pick it up by file mode + name.

Index

Constants

This section is empty.

Variables

View Source
var ErrLimit = errors.New("safearchive: archive exceeded safety limits")

ErrLimit is the fail-closed family: the archive exceeded a bound or carried a hostile entry. Extraction stopped; the destination holds a PARTIAL tree which callers must discard (the coremgr/provider pipelines unpack into staging and remove it on failure).

Functions

func Unpack

func Unpack(archivePath, dst string, limits Limits) error

Unpack extracts archivePath into dst with the given limits. The format is selected by file extension, falling back to content sniffing (PK zip magic / gzip magic) for misnamed files.

Types

type Limits

type Limits struct {
	// MaxArchiveBytes bounds the staged archive FILE size. The check
	// runs before any entry is read.
	MaxArchiveBytes int64

	// MaxTotalBytes bounds the sum of all extracted file sizes.
	MaxTotalBytes int64

	// MaxFileBytes bounds one extracted file.
	MaxFileBytes int64

	// MaxFiles bounds the number of extracted entries (files and
	// directories).
	MaxFiles int
}

Limits bounds one extraction. Zero fields mean "no limit of this kind" — but callers handling remotely acquired archives must always set all four (DefaultLimits provides the shared safe values).

func DefaultLimits

func DefaultLimits() Limits

DefaultLimits returns the shared extraction budget for FreeIran's remotely acquired core/provider archives: archives up to 512 MiB, total expansion capped at 2 GiB, single files capped at 1 GiB and at most 4096 entries. These comfortably cover every official Xray/V2Ray/sing-box/Tor/Psiphon release shape while keeping a hostile archive orders of magnitude away from exhausting disk or memory.

Jump to

Keyboard shortcuts

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