Skip to content
Verified reproduction

GHSA-8qq5-rm4j-mr97: node-tar Arbitrary File Overwrite via Hardlink Escape

GHSA-8qq5-rm4j-mr97 is verified against tar · npm This high reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00065.

REPRO-2026-00065 tar · npm Jan 17, 2026 .txt
Severity HIGH
Confidence HIGH
Reproduced in 6m 8s
Tool calls 102
Spend $0.79
$ pruva-verify REPRO-2026-00065
or curl -O https://pruva.dev/api/v1/reproductions/REPRO-2026-00065/artifacts/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh
Run in a VM or disposable container. This exploits a real vulnerability.
02 · The vulnerability

The node-tar library (<= 7.5.2) fails to sanitize the linkpath of Link (hardlink) and SymbolicLink entries when preservePaths is false (the default secure behavior). This allows malicious archives to bypass the extraction root restriction, leading to Arbitrary File Overwrite via hardlinks and Symlink Poisoning via absolute symlink targets.

03 · Root cause
## Summary
`node-tar` ≤ 7.5.2 does not sanitize the `linkpath` field of `Link` entries when extracting with `preservePaths=false`. A malicious TAR can hardlink a file inside the extraction root (e.g., `payload`) to an absolute path outside the root (e.g., `/tmp/secret.txt`). When the extractor later writes to the in-root path, it actually overwrites the arbitrary external file, enabling path-escape and arbitrary file overwrite.

## Impact
- **Affected component:** `node-tar` hardlink extraction logic (`unpack.ts`)
- **Affected versions:** 7.5.2 and earlier (fixed in 7.5.3)
- **Risk:** High. Attackers controlling TAR input can overwrite any writable file reachable by the extracting process, enabling configuration tampering or code execution in build/CI pipelines.

## Root Cause
`node-tar` resolves hardlink targets with `path.resolve(this.cwd, entry.linkpath)` but never checks that the resulting path still resides under `cwd`. Because `path.resolve` returns the second operand unchanged when it is absolute, an attacker can supply an absolute `linkpath`. The library then creates a hardlink from the in-root `entry.path` to the attacker-chosen absolute file. Subsequent writes to `entry.path` therefore modify the external target. Fix commit (upstream): https://github.com/isaacs/node-tar/commit/340eb285b6d986e91969a1170d7fe9b0face405e adds validation to reject absolute link targets.

## Reproduction Steps
1. Run `repro/reproduction_steps.sh`.
2. Script installs Node dependencies (including `node-tar@7.5.2`), crafts a malicious TAR with a hardlink pointing to `secret.txt` outside the extraction root, extracts it with `tar.x({preservePaths:false})`, writes `EXPLOIT` into `out/payload`, and finally reads `secret.txt`.
3. Reproduction succeeds when the script reports `secret.txt now contains: EXPLOIT` and exits 0.

## Evidence
- Logs: `logs/repro_20260117075559.log`, `logs/repro_20260117075603.log`
- Key excerpt: `secret.txt now contains: EXPLOIT` followed by `Reproduction successful: secret.txt overwritten via hardlink escape`
- Environment: Node v22.21.1, npm 10.9.4 as captured in the log prologue.

## Recommendations / Next Steps
- Upgrade to `node-tar` ≥ 7.5.3 where absolute link targets are rejected.
- When possible, reject TAR archives containing `Link`/`SymbolicLink` entries or perform manual validation that resolved paths stay inside the extraction root.
- Add regression tests that extract crafted archives with absolute `linkpath`s to ensure future sanitization.

## Additional Notes
- Script is idempotent: executed twice consecutively; both runs succeeded and produced separate timestamped logs.
- Limitation: PoC demonstrates hardlink overwrite only; symlink poisoning is related but not exercised here.
04 · Reproduction transcript

The agent's step-by-step process — every tool call, every handoff, the moment the exploit fired. Phases: support triages the advisory · repro reproduces it · vuln_variant confirms the fix blocks it · judge verifies.

Loading session...

05 · Artifacts

Scripts, logs, diffs, and output captured during the reproduction.

No artifacts available