GHSA-gvwx-54wh-qm9j: node-tar: Uncaught Exception DoS via NUL byte in PAX path/linkpath records
Summary
node-tar strips trailing NUL bytes from long-name (L) and long-linkpath (K) GNU extended headers but does not apply the same sanitization to equivalent fields delivered via PAX (x typeflag) extended headers. A PAX record of the form path=visible.txt\x00hidden.txt is parsed verbatim into entry.path and flows into fs.lstat() / fs.open(), which Node.js core rejects with ERR_INVALID_ARG_VALUE. The throw originates inside an FSReqCallback async chain that is not wrapped by the consumer's await/try-catch around tar.x() — it surfaces as uncaughtException and terminates the process.
This is a remote denial-of-service primitive against any process that extracts attacker-supplied tarballs through tar.x / tar.extract / tar.t / tar.Parser, even when the consumer follows the documented try/catch error-handling pattern.
A secondary parser-differential (CWE-436) exists because tar(1), bsdtar, and Python tarfile truncate the path at the first NUL (yielding visible.txt) while node-tar retains the full string. A validator that pre-scans a tarball with one tool and extracts with the other is bypassed.
Root cause
Vulnerable sink — src/pax.ts:157-183
PAX KV records flow through parseKVLine. The value half (v) is assigned directly to the result object with no sanitization for embedded NUL bytes:
// src/pax.ts:157
const parseKVLine = (set: Record<string, unknown>, line: string) => {
const n = parseInt(line, 10)
if (n !== Buffer.byteLength(line) + 1) return set
line = line.slice((n + ' ').length)
const kv = line.split('=')
const r = kv.shift()
if (!r) return set
const k = r.replace(/^SCHILY\.(dev|ino|nlink)/, '$1')
const v = kv.join('=') // <-- NO NUL STRIP
set[k] =
/^([A-Z]+\.)?([mac]|birth|creation)time$/.test(k) ?
new Date(Number(v) * 1000)
: /^[0-9]+$/.test(v) ? +v
: v // <-- v with NULs lands here
return set
}
The PAX record body is length-prefixed, so the parser knows the exact byte boundary — but it never checks whether the value half between = and \n contains NUL. T
Details
Original advisory: https://github.com/advisories/GHSA-gvwx-54wh-qm9j
Exploitation outlook
EPSS (FIRST.org) estimates each CVE’s probability of exploitation in the next 30 days — here is the CSIRTS.com read on those numbers.
- Low exploitation riskCVE-2026-598750.29% 30-day exploitation probability — currently an unlikely target, but scores change as exploit code circulates. Riskier than 21% of all scored CVEs.
Referenced CVEs
| CVE | CSIRTS overview | External |
|---|---|---|
| CVE-2026-59875 | coverage & exploitation status | NVD · CVE.org |
Same CVEs, other sources
How other CERTs, PSIRTs and databases cover the vulnerabilities in this advisory.
More from GitHub Security Advisories
- mediumGHSA-jr6p-8pjj-mfx6: Capsule has an incomplete fix of CVE-2026-22872: TenantResource RawItems and Generators s…2026-07-31
- mediumGHSA-68cj-mvg9-rgm2: Capsule: CapsuleConfiguration NodeMetadata regex fields lack webhook validation, allowing…2026-07-31
- mediumGHSA-ff84-5f28-78qj: re2: Out-of-bounds heap read in `exec`/`test`/`match` via attacker-influenced `lastIndex`…2026-07-31
- mediumGHSA-6hxr-mr5r-9836: re2: Global `String.prototype.match` with an empty-matchable pattern never advances → inf…2026-07-31
- mediumGHSA-x83g-979r-f5fh: Sylius Mollie Plugin has unauthenticated IDOR that leaks order token and customer PII2026-07-31