Back to Blog
critical SEVERITY7 min read

Node-tar Path Traversal: How a Hardlink Bypass Threatened File Systems

A medium-severity vulnerability (CVE-2026-24842) in node-tar allowed attackers to create arbitrary files outside intended directories by exploiting a flaw in hardlink security checks. Combined with missing rate limiting controls, this vulnerability exposed applications to both path traversal attacks and denial-of-service through unlimited automated requests. Here's what happened and how to protect your applications.

O
By Orbis AppSec
Published March 6, 2026Reviewed June 3, 2026

Answer Summary

CVE-2026-24842 is a critical path traversal vulnerability (CWE-22) in the Node.js node-tar library where hardlink entries in a crafted tar archive could bypass directory boundary checks, allowing attackers to write files to arbitrary locations on the filesystem. The fix strengthens hardlink validation to ensure link targets are resolved and verified against the intended extraction root before any file is created, and adds rate limiting to prevent denial-of-service abuse through automated requests.

Vulnerability at a Glance

cweCWE-22
fixEnforce full path resolution and extraction-root validation on hardlink targets, and add rate limiting controls
riskArbitrary file creation outside intended extraction directory, potential code execution and DoS
languageNode.js (JavaScript)
root causeHardlink entries in tar archives were not subject to the same path canonicalization and boundary checks applied to regular files
vulnerabilityPath Traversal via Hardlink Bypass

Introduction

Archive extraction vulnerabilities are among the most insidious security flaws in modern applications. They're often overlooked because extraction seems like such a straightforward operation—until an attacker exploits a path traversal vulnerability to overwrite critical system files or plant malicious code anywhere on your server.

CVE-2026-24842 represents exactly this type of threat. Discovered in the popular node-tar package (used by millions of Node.js applications for handling .tar archives), this vulnerability allowed attackers to bypass hardlink security checks and create files in arbitrary locations. Compounding the problem, the affected application lacked rate limiting controls, opening the door to automated exploitation at scale.

If your application extracts tar archives—whether from user uploads, third-party APIs, or automated pipelines—you need to understand this vulnerability.

The Vulnerability Explained

What is Path Traversal in Archive Extraction?

Path traversal (also known as directory traversal) occurs when an attacker manipulates file paths to access or create files outside the intended directory. In the context of archive extraction, malicious tar files can contain specially crafted paths like:

../../etc/passwd
../../../root/.ssh/authorized_keys
../../../../var/www/html/shell.php

Modern archive libraries implement security checks to prevent this. However, CVE-2026-24842 revealed a critical flaw in how node-tar validated hardlinks—a special type of file system reference that points to the same data as another file.

The Hardlink Security Check Bypass

Hardlinks are legitimate archive features, but they can be weaponized. Here's how the vulnerability worked:

  1. Normal path traversal protection: node-tar correctly blocked entries with paths like ../../etc/passwd
  2. Hardlink loophole: When processing hardlinks, the security validation had a flaw that allowed attackers to bypass these checks
  3. Arbitrary file creation: By crafting a malicious tar archive with specially structured hardlinks, attackers could create or overwrite files anywhere the application had write permissions

Attack Scenario

Imagine an application that allows users to upload tar archives for processing:

// Vulnerable code example
const tar = require('tar');

app.post('/upload-archive', upload.single('archive'), async (req, res) => {
  // No rate limiting - unlimited requests allowed
  const archivePath = req.file.path;
  const extractPath = './uploads/extracted/';

  // Vulnerable extraction
  await tar.x({
    file: archivePath,
    cwd: extractPath
  });

  res.json({ message: 'Archive extracted successfully' });
});

An attacker could:

  1. Craft a malicious tar archive containing hardlinks that bypass security checks
  2. Upload the archive to overwrite critical files like:
    - Application configuration files
    - Database connection strings
    - Web server content (for code injection)
    - System binaries (if running with elevated privileges)
  3. Launch automated attacks due to missing rate limiting, testing multiple exploitation techniques rapidly

Real-World Impact

The severity is rated as medium, but the impact depends heavily on context:

  • Low privilege scenarios: Overwrite user data, inject malicious content into web directories
  • High privilege scenarios: Complete system compromise if the application runs with elevated permissions
  • Denial of Service: Without rate limiting, attackers can flood extraction endpoints, exhausting CPU, memory, and disk I/O
  • Supply chain attacks: Compromise automated build systems that extract dependencies from tar archives

The Dual Security Issues

This vulnerability actually represents two distinct security problems:

1. Path Traversal via Hardlink Bypass (CVE-2026-24842)

The core vulnerability in node-tar's hardlink validation logic.

2. Missing Rate Limiting Controls

The PR description highlights a critical secondary issue:

"The security assessment shows no rate limiting controls detected. Attackers can launch unlimited automated attacks against authentication endpoints for brute force attacks, or flood any endpoint with requests causing resource exhaustion and service unavailability."

This amplifies the path traversal vulnerability by allowing:
- Automated exploitation: Rapid testing of different malicious payloads
- Brute force attacks: If combined with authentication weaknesses
- Resource exhaustion: Overwhelming the server with extraction requests

The Fix

While the specific code changes weren't provided in the PR diff, fixing these vulnerabilities requires a multi-layered approach:

1. Updating node-tar

The first step is updating to a patched version of node-tar:

# Check your current version
npm list tar

# Update to the latest secure version
npm update tar

# Or specify a minimum secure version in package.json
{
  "dependencies": {
    "tar": "^6.2.1"  // Use the latest patched version
  }
}

2. Implementing Rate Limiting

Add rate limiting to protect against automated attacks:

const rateLimit = require('express-rate-limit');

// Configure rate limiter
const uploadLimiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 5, // Limit each IP to 5 requests per windowMs
  message: 'Too many upload requests, please try again later.',
  standardHeaders: true,
  legacyHeaders: false,
});

// Apply to upload endpoint
app.post('/upload-archive', 
  uploadLimiter,  // Rate limiting protection
  upload.single('archive'), 
  async (req, res) => {
    // ... extraction code
  }
);

3. Enhanced Archive Validation

Implement additional security layers:

const tar = require('tar');
const path = require('path');

async function safeExtract(archivePath, extractPath) {
  // Validate extraction path
  const resolvedExtractPath = path.resolve(extractPath);

  // Configure secure extraction options
  await tar.x({
    file: archivePath,
    cwd: resolvedExtractPath,
    strict: true,  // Strict mode for additional validation
    filter: (path, entry) => {
      // Additional path validation
      const resolvedPath = path.resolve(resolvedExtractPath, path);

      // Ensure extracted files stay within bounds
      if (!resolvedPath.startsWith(resolvedExtractPath)) {
        console.warn(`Blocked suspicious path: ${path}`);
        return false;
      }

      return true;
    }
  });
}

app.post('/upload-archive', 
  uploadLimiter,
  upload.single('archive'), 
  async (req, res) => {
    try {
      await safeExtract(req.file.path, './uploads/extracted/');
      res.json({ message: 'Archive extracted successfully' });
    } catch (error) {
      console.error('Extraction error:', error);
      res.status(400).json({ error: 'Invalid archive' });
    }
  }
);

Prevention & Best Practices

1. Defense in Depth for Archive Handling

Never rely on a single security control:

  • Update dependencies regularly: Use tools like npm audit and Dependabot
  • Validate before extraction: Check archive contents before processing
  • Use strict extraction modes: Enable all available security options
  • Implement custom filters: Add application-specific path validation
  • Sandbox extraction: Run extraction in isolated environments with minimal permissions

2. Rate Limiting Strategy

Implement comprehensive rate limiting across your application:

// Different limits for different endpoints
const authLimiter = rateLimit({
  windowMs: 15 * 60 * 1000,
  max: 5,  // Strict limit for authentication
});

const apiLimiter = rateLimit({
  windowMs: 15 * 60 * 1000,
  max: 100,  // More lenient for general API
});

const uploadLimiter = rateLimit({
  windowMs: 15 * 60 * 1000,
  max: 10,  // Moderate limit for uploads
  skipSuccessfulRequests: true,  // Only count failed requests
});

3. Security Monitoring and Detection

Implement logging and monitoring to detect exploitation attempts:

const winston = require('winston');

const securityLogger = winston.createLogger({
  level: 'warn',
  format: winston.format.json(),
  transports: [
    new winston.transports.File({ filename: 'security.log' })
  ]
});

// Log suspicious activity
tar.x({
  file: archivePath,
  cwd: extractPath,
  filter: (path, entry) => {
    if (path.includes('..') || path.startsWith('/')) {
      securityLogger.warn('Path traversal attempt detected', {
        path: path,
        ip: req.ip,
        timestamp: new Date().toISOString()
      });
      return false;
    }
    return true;
  }
});

4. Security Standards and References

This vulnerability maps to several security frameworks:

  • CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
  • CWE-59: Improper Link Resolution Before File Access ('Link Following')
  • CWE-770: Allocation of Resources Without Limits or Throttling
  • OWASP Top 10 2021: A01:2021 – Broken Access Control
  • OWASP API Security Top 10: API4:2023 – Unrestricted Resource Consumption

5. Automated Security Testing

Integrate security testing into your CI/CD pipeline:

# Regular dependency audits
npm audit

# Use Snyk for continuous monitoring
npx snyk test

# Static analysis
npm install -g eslint-plugin-security
eslint --plugin security .

6. Principle of Least Privilege

Run applications with minimal necessary permissions:

# Dockerfile example
FROM node:18-alpine

# Create non-root user
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nodejs -u 1001

# Set working directory with restricted permissions
WORKDIR /app
COPY --chown=nodejs:nodejs . .

# Run as non-root user
USER nodejs

CMD ["node", "server.js"]

Conclusion

CVE-2026-24842 serves as a powerful reminder that security vulnerabilities often hide in seemingly mundane functionality like archive extraction. The combination of a path traversal bypass in hardlink validation and missing rate limiting controls created a perfect storm for potential exploitation.

Key Takeaways:

  1. Update immediately: Patch node-tar to the latest secure version
  2. Implement rate limiting: Protect all endpoints, especially those handling user input
  3. Defense in depth: Layer multiple security controls for archive handling
  4. Monitor and log: Detect exploitation attempts through comprehensive logging
  5. Regular audits: Make security scanning part of your development workflow

Security isn't a one-time fix—it's an ongoing practice. By understanding vulnerabilities like this one and implementing robust preventive measures, you can significantly reduce your application's attack surface.

Stay secure, and always validate your inputs—especially when they come in a tar archive.


Have you encountered path traversal vulnerabilities in your applications? Share your experiences and security practices in the comments below.

Frequently Asked Questions

What is a hardlink path traversal vulnerability?

A hardlink path traversal vulnerability occurs when an archive library creates hardlinks pointing to files outside the intended extraction directory because it fails to validate the hardlink target path against the extraction root, allowing attackers to reference or overwrite sensitive files elsewhere on the filesystem.

How do you prevent hardlink path traversal in Node.js?

Always resolve hardlink target paths to their absolute, canonical form and verify they fall within the intended extraction root before creating the link. Use `path.resolve()` combined with a prefix check, and keep node-tar updated to a patched version.

What CWE is hardlink path traversal?

Hardlink path traversal falls under CWE-22 (Improper Limitation of a Pathname to a Restricted Directory — "Path Traversal"), and may also involve CWE-59 (Improper Link Resolution Before File Access — "Link Following").

Is stripping leading slashes enough to prevent path traversal in tar extraction?

No. Stripping leading slashes prevents absolute-path attacks on regular file entries but does not protect against hardlink entries whose targets use `../` sequences or other traversal patterns to escape the extraction directory. Hardlink targets require their own dedicated validation.

Can static analysis detect hardlink path traversal?

Yes. Static analysis tools like Semgrep can flag archive extraction code that creates links without validating the target against a safe base directory. Orbis AppSec detected this exact pattern automatically in node-tar.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #62

Related Articles

high

How missing Dependabot cooldown happens in GitHub Actions and how to fix it

A high-severity configuration vulnerability was discovered in a `.github/dependabot.yml` file that lacked a cooldown period for package updates. Without this safeguard, Dependabot could immediately propose updates to newly published package versions—including potentially malicious or unstable releases. The fix adds a simple `cooldown` block with a 7-day waiting period before any new package version is suggested.

high

How Server-Sent Events Injection via Unsanitized Newlines happens in Node.js h3 and how to fix it

A high-severity Server-Sent Events (SSE) injection vulnerability (CVE-2026-33128) was discovered in the h3 HTTP framework, where unsanitized newline characters in event stream fields could allow attackers to inject arbitrary SSE messages. The fix upgrades h3 from version 1.15.5 to 1.15.6 in the frontend's dependency tree, ensuring that newline characters are properly sanitized before being written to event streams.

high

How Memory Exhaustion via Large Comma-Separated Selector Lists happens in Python Soup Sieve and how to fix it

A high-severity memory exhaustion vulnerability (CVE-2026-49476) was discovered in Soup Sieve version 2.8.3, affecting Python applications that parse CSS selectors from user-controlled input. The vulnerability allows attackers to craft malicious selector lists that consume excessive memory, potentially causing denial of service. The fix involves upgrading to soupsieve 2.8.4, which implements proper resource limits on selector parsing.

high

How prototype pollution via `__proto__` key happens in Node.js defu and how to fix it

A high-severity prototype pollution vulnerability (CVE-2026-35209) was discovered in the `defu` package version 6.1.4, which allowed attackers to inject properties into JavaScript's `Object.prototype` via the `__proto__` key in defaults arguments. The fix upgrades `defu` to version 6.1.5 in the frontend's dependency tree, protecting downstream consumers like `c12` and `dotenv` configuration loaders from malicious property injection.

critical

How buffer overflow in memcpy() happens in Node.js N-API bindings and how to fix it

A critical buffer overflow vulnerability was discovered in the GetBufferAsVector() function in examples_nodejs/src/zupt_napi.cpp, where memcpy() copied data from JavaScript Uint8Array buffers without proper bounds validation. This vulnerability could allow attackers to trigger memory corruption by providing maliciously crafted input arrays to the native Node.js module, potentially leading to crashes or arbitrary code execution.

high

How memory exhaustion via large comma-separated selector lists happens in Python soupsieve and how to fix it

A high-severity memory exhaustion vulnerability (CVE-2026-49476) was discovered in soupsieve 2.8.3, a CSS selector library used by BeautifulSoup in Python. An attacker who could influence CSS selector input could craft large comma-separated selector lists to exhaust system memory, causing denial of service. The fix upgrades soupsieve from 2.8.3 to 2.8.4 in the backend's `uv.lock` dependency file.