async-tar v0.6.0 mis-applies a buffered PAX size extension to an intermediary
extension header (a GNU longname L, a GNU longlink K, or a PAX x/g
header) instead of to the next file entry. POSIX requires a PAX extended-header
record set to describe the next file entry, never an intervening extension
header. Because poll_next_raw (src/archive.rs) threads the buffered PAX
records into the size computation of whatever raw header it reads next — and that
header can be an intermediary L — the stream cursor is advanced by an
attacker-chosen amount when the L body is consumed. The parser then desyncs
relative to a POSIX-correct tar parser (e.g. GNU tar), reading subsequent bytes
at the wrong block boundary.
An attacker who can influence a tar stream that an async-tar consumer extracts
can construct an x → L → file sequence whose entry list and on-disk result
differ between async-tar and a reference parser. This enables content/entry
smuggling: a file that a GNU-tar-based scanner/validator/AV sees as benign opaque
data is extracted by async-tar as a different file with different bytes (e.g. an
executable script), and vice versa.
Type confusion / improper validation of the specified quantity (size). CWE-20, CWE-843. Severity assessed Medium, consistent with the same defect class in the upstream tar-rs / tokio-tar lineage.
Package: async-tar (crates.io). Affected version: 0.6.0 (latest release) and
current main HEAD. Both lack the extension-header guard.
src/archive.rs, poll_next_raw (line numbers from the v0.6.0 tag,
commit 45814b19295b7398e119c90c57d8c8bf70a798b6):
let file_pos = *next;
let mut header = current_header.take().unwrap();
// when pax extensions are available, the size should come from there.
let mut size = header.entry_size()?;
// the size above will be overriden by the pax data if it has a size field.
// same for uid and gid, which will be...
0.6.1Exploitability
AV:NAC:LAT:PPR:NUI:NVulnerable System
VC:NVI:LVA:NSubsequent System
SC:NSI:NSA:N6.3/CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N