Bug description
preScanTarGz validates PAX path and linkpath overrides, but it does not
apply GNU L (long name) and K (long link) records to the following entry.
Zig 0.16's TAR iterator does apply those records. Malt can therefore validate
the placeholder ustar name or link target while std.tar.pipeToFileSystem
extracts a different effective value.
This is not a claim that std.tar fails to sanitize entry names. Zig calls
sanitizePath on the effective entry name. The mismatch is in Malt's pre-scan.
sanitizePath does not validate symlink targets, and Malt cannot track a
symlink whose GNU long name it never applied.
A malicious bottle can use GNU K to create a symlink with an escaping target
after Malt approved a benign placeholder. It can also use GNU L to hide a
symlink's effective name and then write a later file through that symlink
outside the extraction directory.
Affected code:
Regression tests:
extractTarGz rejects an escaping GNU long-link target
extractTarGz rejects a write through a GNU long-named symlink
extractTarGz accepts safe GNU long-name and long-link metadata
Homebrew catalog reference
No official trigger was found in the bounded archive sample. The scan checked
13,457 entries from the fontconfig, libpng, node, openssl@3,
proctools, sqlite, unzip, xz, zstd, minimal-racket, nagios, and
unbound bottles. None used a GNU L or K record. The formula API does not
expose bottle entry types, so this does not rule out other or historical
bottles.
Expected behavior
The pre-scan must consume GNU L and K records with the same one-entry
lifetime and size/NUL rules as Zig's iterator. It must validate the same name
and link target that extraction will use. Malt's existing Rust-bottle-compatible
one-level symlink policy must remain intact.
Fix: #838
Bug description
preScanTarGzvalidates PAXpathandlinkpathoverrides, but it does notapply GNU
L(long name) andK(long link) records to the following entry.Zig 0.16's TAR iterator does apply those records. Malt can therefore validate
the placeholder ustar name or link target while
std.tar.pipeToFileSystemextracts a different effective value.
This is not a claim that
std.tarfails to sanitize entry names. Zig callssanitizePathon the effective entry name. The mismatch is in Malt's pre-scan.sanitizePathdoes not validate symlink targets, and Malt cannot track asymlink whose GNU long name it never applied.
A malicious bottle can use GNU
Kto create a symlink with an escaping targetafter Malt approved a benign placeholder. It can also use GNU
Lto hide asymlink's effective name and then write a later file through that symlink
outside the extraction directory.
Affected code:
extractTarGz,preScanTarGz, and the GNU metadata branch insrc/fs/archive.zig:93-319std/tar.zig: GNU metadata is applied by the iterator at lines430-435, while extraction sanitizes the effective entry name at lines
601-643.
Regression tests:
extractTarGz rejects an escaping GNU long-link targetextractTarGz rejects a write through a GNU long-named symlinkextractTarGz accepts safe GNU long-name and long-link metadataHomebrew catalog reference
No official trigger was found in the bounded archive sample. The scan checked
13,457 entries from the
fontconfig,libpng,node,openssl@3,proctools,sqlite,unzip,xz,zstd,minimal-racket,nagios, andunboundbottles. None used a GNULorKrecord. The formula API does notexpose bottle entry types, so this does not rule out other or historical
bottles.
Expected behavior
The pre-scan must consume GNU
LandKrecords with the same one-entrylifetime and size/NUL rules as Zig's iterator. It must validate the same name
and link target that extraction will use. Malt's existing Rust-bottle-compatible
one-level symlink policy must remain intact.
Fix: #838