GitHub Advisoryadvisory · npm
GHSA-gvwx-54wh-qm9j node-tar: Uncaught Exception DoS via NUL byte in PAX path/linkpath records
MEDIUM
Official page ↗
- Aliases
- CVE-2026-59875
- Ecosystem
- npm
- Packages
- tar
- Severity
- Moderate
- CVSS vector
- CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L
- Weaknesses
- CWE-248
- Reviewed
- 2026-07-20
Affected packages
• npm tar: < 7.5.17 → fixed in 7.5.17
Description
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:
```ts
// src/pax.ts:157
const parseKVLine = (set: Record, 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('=') // {
console.log("UNCAUGHT:", e.code, "-", e.message);
process.exit(99);
});
import("tar").then(async tar => {
try {
await tar.x({ file: "../poc.tar", cwd: "./out" });
console.log("NORMAL_RETURN");
} catch (e) {
console.log("CAUGHT_BY_USER:", e.code);
}
});'
```
Observed output (verified 2026-06-23 against `[email protected]`)
```
UNCAUGHT: ERR_INVALID_ARG_VALUE - The argument 'path' must be a string,
Uint8Array, or URL without null bytes.
Received '/.../out/visible.txt\x00hidden.txt'
exit: 99
```
The exception bypasses the user's `try { await tar.x(...) } catch (e) { ... }` block and lands in the global `uncaughtException` handler. In a typical server without that handler, the process exits.
---
Impact
Direct: remote DoS
Any service that ingests attacker-supplied tarballs via node-tar inherits a one-tarball-kills-the-process primitive. Realistic deployments where this is reachable without user interaction:
• npm registry tarball ingestion and downstream mirrors
• GitHub Actions cache restore (`actions/cache`, `actions/setup-*` extracting toolchains)
• Container image build pipelines that unpack layer tarballs through node tooling
• Backup-restore services accepting user uploads
• CI artifact processors and badge generators
• Static-site / Docusaurus / Next.js build runners that fetch and extract dep tarballs
• Cloud functions that auto-extract uploaded archives
A correctly-coded consumer that does:
```js
try {
await tar.x({ file: req.upload.path, cwd: tmpdir });
} catch (e) {
return res.status(400).json({ error: 'bad archive' });
}
```
does not catch this throw. The Node process dies and (depending on the supervisor) the worker may take time to respawn or never respawn if it dies during boot.
Secondary: parser-differential validator bypass (CWE-436)
| Tool | Result for `path=visible.txt\x00hidden.txt` |
|----------------------------|----------------------------------------------|
| GNU tar (`tar -tvf`) | Lists `visible.txt` (truncated at NUL) |
| `bsdtar -tvf` | Lists `visible.txt` (truncated at NUL) |
| Python `tarfile.list()` | Lists `visible.txt\x00hidden.txt` (raw)…
Related
Alias · CVE (1)
- CVE-2026-59875 node-tar is a tar archive manipulation library for Node.js. vulnerability
Weakness · CWE (1)
- CWE-248 Uncaught Exception weakness
References
- https://github.com/isaacs/node-tar/security/advisories/GHSA-gvwx-54wh-qm9j web
- https://nvd.nist.gov/vuln/detail/CVE-2026-59875 advisory
- https://github.com/isaacs/node-tar/commit/7a635c29f5edbf083557374d43984273ecfed5b3 web
- https://github.com/isaacs/node-tar package
- https://github.com/isaacs/node-tar/releases/tag/v7.5.17 web