Andrew Mercer
on this page

Compression Gotchas and Safety

Tarbombs

A tarbomb is an archive without a single top-level directory that sprays files across your current directory, sometimes overwriting existing ones. Always look first:

tar tf archive.tar.gz | head
unzip -l archive.zip | head

Or extract into a fresh directory:

mkdir out && tar xf archive.tar.gz -C out

aunpack, dtrx and unar do this automatically (universal extractors).

Decompression bombs

A small file that expands to an enormous size (gigabytes or terabytes) can fill a disk or exhaust memory. With untrusted input, check the declared size first and enforce limits:

gzip -l file.gz         # unreliable over 4 GiB
xz -l file.xz
zstd -l file.zst
unzip -l file.zip

In services, cap the total bytes written and the number of entries rather than trusting headers, which can lie.

Path traversal ("zip slip")

Malicious archives can contain entries like ../../etc/cron.d/x, absolute paths, or symlinks that point outside the destination followed by files written "through" them.

  • GNU tar strips leading / and refuses .. components by default.
  • Info-ZIP unzip strips ../ components.
  • Library code and less careful tools may do neither.

Never extract untrusted archives as root, and validate every path when extracting programmatically (see Rust).

Never run an untrusted shar

Shell archives (.shar) are scripts that recreate files when run. Read them, or use unshar, rather than executing them.

Source files disappear (or don't)

Tool Default behaviour on the input file
gzip, bzip2, xz, lzip, compress Deletes it (-k keeps it)
zstd, lz4, brotli, lzop Keeps it (--rm / -U deletes it)
tar, zip, 7z Never touch sources

Scripts that switch from gzip to zstd and rely on the source being removed will quietly double their disk usage.

Flag order and argument traps

  • With bundled tar flags, f must come last: tar czf name.tar.gz, not tar cfz (which creates an archive named z).
  • Arguments after the archive name in tar x are members to extract, not a destination. Use -C dir.
  • Match the compression flag to the file when listing (tar tjvf file.tar.gz fails), or omit it and let tar detect it.
  • tar -C applies only to the arguments that follow it.
  • 7z -o takes its value with no space: -o/tmp/dest.
  • lz4 in out treats the second filename as the output, unlike most tools.

Compress, then encrypt

Encrypted data doesn't compress. Also avoid weak encryption: zip -e (ZipCrypto) and openssl des3 without -pbkdf2. See encryption.

Operations that need uncompressed tarballs

tar -r (append), -u (update), --delete, and -W (verify) only work on plain .tar. Decompress, modify, recompress — or keep a plain tar and compress at the end.

Data that won't compress

JPEG, PNG, MP3, MP4, existing archives, and encrypted data barely shrink. Store them instead of recompressing (zip -n, 7z -mx=0, plain tar).

Many tiny files compressed individually compress poorly (no shared history, plus per-file overhead). Tar them first, or use zstd dictionaries.

Metadata and special files

Feature tar/cpio zip 7z
Unix permissions Yes Mostly (Info-ZIP) Partially
Owners/groups Yes No No
Symlinks Yes With -y Partially
Hard links Yes No No
Device files, FIFOs Yes No No
ACLs, xattrs, SELinux labels With flags (GNU tar) No No
Sparse files With -S No No

Use tar for system backups.

Other edge cases

  • Long paths: use --format=posix (pax); ustar limits paths to 255 characters and files to 8 GiB.
  • Restoring ownership: as root, tar restores original owners, which can be surprising in containers; use --no-same-owner. Use --numeric-owner when user names map to different IDs on the target.
  • Memory: high xz presets and zstd --ultra/--long need lots of memory on both ends, and can be OOM-killed in containers.
  • Threads in containers: -T0 sees the host's CPUs. See parallel compression.
  • gzip -l is wrong for files over 4 GiB and for multi-member files.
  • Old xz-utils: versions 5.6.0 and 5.6.1 contain a backdoor. See xz.

See also