Jan 28, 2026·6 min read·73 visits
Logic error in hardlink validation allows writing or linking files outside the destination folder. Affects node-tar < 7.5.7. Fixed by strictly forbidding '..' in link targets.
A critical logic flaw in node-tar, the de facto standard archive utility for the Node.js ecosystem, allows attackers to bypass path traversal protections using hardlinks. By exploiting a discrepancy between how link paths are validated versus how they are resolved by the operating system, a malicious TAR archive can create hardlinks to arbitrary files outside the extraction root. This affects millions of developers and pipelines relying on node-tar for package installation.
If you work with Node.js, you use node-tar. You might not know it, but every time you type npm install, this library is the workhorse silently unpacking tarballs in the background. It is the plumbing of the JavaScript ecosystem. And when the plumbing leaks, the entire house gets wet.
CVE-2026-24842 isn't just a simple buffer overflow or a typo. It's a logic bug that exposes a fundamental misunderstanding of how file systems resolve paths. The vulnerability allows an attacker to craft a TAR archive that looks perfectly innocent to the security validator but behaves maliciously when handed off to the operating system.
Imagine a bouncer checking your ID at the club entrance (the validator). They check your address and say "You live nearby, come in." But once you're inside, you teleport to a different country. That's essentially what happens here. The validator calculates path safety based on one assumption, while the OS executes the file creation based on another.
The core of the issue lies in the discrepancy between intent and execution. When node-tar extracts a file, it generally tries to prevent "Path Traversal"—the classic attack where a file named ../../etc/passwd tries to escape the extraction directory. node-tar has checks for this. However, hardlinks (type: 'Link') introduce a layer of complexity.
When node-tar validated a hardlink entry, it resolved the target path relative to the entry's parent directory within the archive. For example, if you had an entry at a/b/c/link, and it pointed to ../../target, the validator calculated: extract_root/a/b/c/ + ../../target = extract_root/a/target. This looks safe. It stays inside the extraction root.
However, the fatal flaw was in the actual extraction step. node-tar used fs.linkSync(linkpath, entrypath). Crucially, when fs.link receives a relative path, the operating system resolves it relative to the Current Working Directory (CWD) of the process, NOT the directory of the file being created. So, that same ../../target string is passed directly to the OS, which walks up two directories from where the process is running, potentially escaping the sandbox entirely.
The fix provided in commit f4a7aa9bc3d717c987fdf1480ff7a64e87ffdb46 is brutally simple, acknowledging that trying to be clever with path resolution is a losing game. Instead of trying to calculate where the link lands, the developers decided to nuke the problem from orbit.
The vulnerable code attempted to resolve paths intelligently. The patched code simply forbids relative traversals in links altogether.
// src/unpack.ts (The Fix)
// If the field is a path or the type is a Link (hardlink)
if (field === 'path' || type === 'Link') {
// If the path contains '..', it is immediately rejected.
// No complex math, no resolution attempts. Just NO.
if (p.includes('..')) {
this.warn('TAR_ENTRY_ERROR', `${field} contains '..'`, { entry });
return false;
}
}This is a classic "defense in depth" shift. Rather than trusting the complex logic that ensures .. stays within bounds, node-tar now asserts that hardlinks in archives simply shouldn't be navigating up the directory tree at all. It removes the ambiguity that caused the vulnerability.
To exploit this, we need to trick the validator into thinking we are deep inside a directory structure so that it allows us to use .. segments. Then, we rely on the OS to interpret those .. segments relative to the root of the process.
Here is the recipe for disaster:
trap/level1/level2/level3/.level3.../../../../../../etc/passwd.The Validator's View:
It sees the entry at trap/level1/level2/level3/. It sees the target ../../../../../../etc/passwd. It resolves this relative to level3. Mathematically, that might still look "contained" or at least confusing enough to bypass the check depending on the exact validation logic version.
The OS View:
The process calls link("../../../../../../etc/passwd", "path/to/extract/trap/level1/level2/level3/link"). The OS ignores the destination path when resolving the source. It looks at the source string: ../../../../../../etc/passwd. If the node process is running in /home/user/app, this path walks up to root and grabs the shadow file (permissions permitting). You now have a hardlink to the system's password file inside your extraction folder.
Why should you panic? Because hardlinks are bidirectional portals. If an attacker can create a hardlink to a sensitive file (like a config file or /etc/shadow), they gain a direct handle to that file on the host system.
Scenario 1: Information Disclosure
The attacker extracts the malicious archive. The extraction creates a link named funny_pic.jpg that is actually a hardlink to config/database.yml. The application then processes or serves funny_pic.jpg to the user. The attacker downloads their own "image" and gets your database credentials.
Scenario 2: Integrity Violation
The attacker links overwrite_me.txt to /usr/local/bin/startup_script.sh. Later in the extraction or in a subsequent request, the attacker writes data to overwrite_me.txt. Because it's a hardlink, the OS writes that data directly into startup_script.sh. The next time the server restarts, the attacker owns the box.
The only reliable way to fix this is to upgrade node-tar. The logic required to safely validate hardlinks without banning .. is notoriously difficult and prone to edge cases (as proven by the existence of this CVE).
Remediation Steps:
package-lock.json or yarn.lock for node-tar (often aliased simply as tar).npm audit fix if applicable, or manually force the dependency update.> [!NOTE] > If you cannot upgrade, you must ensure that your application creates a clean, empty sandbox directory for every extraction and strictly limits the file system permissions of the Node.js process. Do not run extraction as root.
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:L/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
node-tar isaacs | < 7.5.7 | 7.5.7 |
| Attribute | Detail |
|---|---|
| CWE | CWE-22 (Path Traversal) |
| Attack Vector | Local / Network (Archive Upload) |
| CVSS | 8.2 (High) |
| EPSS Score | 0.00027 (Low Probability) |
| Confidentiality | High (File Read) |
| Integrity | Low (File Overwrite) |
| Exploit Status | PoC Available |
Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')