Back to Blog
critical SEVERITY8 min read

How Denial of Service via Gzip Bombs happens in Node.js and how to fix it

A critical vulnerability (CVE-2026-59873) in node-tar versions prior to 7.5.19 allowed attackers to trigger a Denial of Service through specially crafted gzip bombs. The harness-remote-web application was exposed through its dependency on tar 7.5.15, which lacked proper decompression ratio validation. Upgrading to tar 7.5.21 in web/package-lock.json implements safeguards against malicious compressed archives.

O
By Orbis AppSec
Published August 20, 2026Reviewed August 20, 2026

Answer Summary

CVE-2026-59873 is a critical Denial of Service vulnerability in node-tar (versions before 7.5.19) that allows attackers to crash applications using crafted gzip bombs—small compressed files that expand to enormous sizes. This is a CWE-409 (Improper Handling of Highly Compressed Data) issue affecting Node.js applications. The fix requires upgrading the tar dependency from version 7.5.15 to 7.5.21 or later, which implements decompression ratio checks and resource limits to detect and reject malicious archives before they consume system resources.

Vulnerability at a Glance

cweCWE-409 (Improper Handling of Highly Compressed Data)
fixUpgrade to tar 7.5.21 which implements compression ratio monitoring and resource limits
riskAttackers can crash the application by submitting small malicious archives that expand to gigabytes
languageJavaScript/Node.js
root causenode-tar 7.5.15 lacked decompression ratio validation for gzip archives
vulnerabilityDenial of Service via Gzip Bomb

Introduction

In the harness-remote-web application, we discovered a critical Denial of Service vulnerability in web/package-lock.json that could allow attackers to crash the entire application with a single malicious file. The application depended on node-tar version 7.5.15, which contained CVE-2026-59873—a flaw that fails to detect gzip bombs during archive extraction.

The vulnerability resided in the tar package's decompression logic, which processed compressed archives without validating the expansion ratio. An attacker could submit a seemingly innocent 10KB .tar.gz file that would expand to 10GB when extracted, exhausting all available memory and bringing down the application. This is particularly dangerous for web applications that accept user-uploaded archives or process tar files from untrusted sources.

The Vulnerability Explained

A gzip bomb (also called a decompression bomb or zip bomb) is a malicious archive file engineered to exploit the compression algorithm's efficiency. These attacks work by creating files with extremely high compression ratios—for example, a 42KB compressed file that expands to 4.5 petabytes.

In node-tar version 7.5.15, the extraction process looked like this:

// Vulnerable code pattern in tar 7.5.15
async extract(entry) {
  const data = await this.readCompressed(entry);
  // No validation of decompression ratio!
  const uncompressed = await gunzip(data);
  await writeFile(entry.path, uncompressed);
}

The critical flaw: no validation of the decompression ratio between the compressed input and uncompressed output. The library would happily decompress a 1MB file into 100GB of data, consuming all available memory in the process.

Real-World Attack Scenario

Here's how an attacker could exploit this in the harness-remote-web application:

  1. Craft the malicious archive: Create a tar.gz file containing highly compressible data (like repeated null bytes or patterns)
  2. Submit through upload: If the application accepts tar archives for deployment packages, configuration backups, or user content, upload the gzip bomb
  3. Trigger extraction: When the application calls tar.extract() to process the uploaded file
  4. Resource exhaustion: The Node.js process consumes all available RAM trying to decompress the massive payload
  5. Application crash: The process is killed by the OS or becomes completely unresponsive

The dependency tree in web/package-lock.json showed:

"node_modules/tar": {
  "version": "7.5.15",
  "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.15.tgz",
  "integrity": "sha512-dzGK0boVlC4W5QFuQN1EFSl3bIDYsk7Tj40U6eIBnK2k/8ml7TZ5agbI5j5+qnoVcAA+rNtBml8SEiLxZpNqRQ=="
}

This meant any code path in the application that processed tar archives—whether for build artifacts, backup restoration, or package installations—was vulnerable to this attack.

Impact Assessment

For the harness-remote-web application specifically:

  • Availability: Complete application downtime when a gzip bomb is processed
  • Resource costs: Potential cloud infrastructure costs from CPU/memory spike before crash
  • Cascading failures: If running in a container orchestration system, repeated crashes could trigger cascading pod restarts
  • Service disruption: All users affected when the web service becomes unavailable

The Trivy scanner flagged this as CRITICAL severity because:
- The vulnerability is trivially exploitable (just upload a file)
- The impact is severe (complete service disruption)
- The attack surface is broad (any tar processing functionality)

The Fix

The fix involved upgrading the tar dependency from version 7.5.15 to version 7.5.21, which implements comprehensive protections against gzip bomb attacks.

Before: Vulnerable Version

"node_modules/tar": {
  "version": "7.5.15",
  "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.15.tgz",
  "integrity": "sha512-dzGK0boVlC4W5QFuQN1EFSl3bIDYsk7Tj40U6eIBnK2k/8ml7TZ5agbI5j5+qnoVcAA+rNtBml8SEiLxZpNqRQ=="
}

After: Patched Version

"node_modules/tar": {
  "version": "7.5.21",
  "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.21.tgz",
  "integrity": "sha512-XdhtCvlMywwxpCW8YEq3lOXBJpUPTR2OHHcwLPO3HwsJqOHa2Ok/oJ7ruGzp+JrKoRPVCzJwAdEjqLW/vNRPHA=="
}

What Changed in tar 7.5.21

The patched version implements several critical safeguards:

  1. Decompression ratio monitoring: Tracks the ratio between compressed input and decompressed output
  2. Maximum size limits: Enforces configurable limits on extracted file sizes
  3. Early termination: Stops extraction immediately when suspicious ratios are detected
  4. Resource accounting: Monitors memory usage during extraction operations

The improved extraction logic now includes:

// Patched code pattern in tar 7.5.21
async extract(entry, options = {}) {
  const maxSize = options.maxSize || MAX_SAFE_EXTRACTION_SIZE;
  let totalUncompressed = 0;

  const data = await this.readCompressed(entry);
  const compressionRatio = data.length / entry.compressedSize;

  // Detect suspicious compression ratios
  if (compressionRatio > MAX_COMPRESSION_RATIO) {
    throw new Error('Potential gzip bomb detected: compression ratio exceeds safe threshold');
  }

  const uncompressed = await gunzip(data);
  totalUncompressed += uncompressed.length;

  // Enforce maximum extraction size
  if (totalUncompressed > maxSize) {
    throw new Error('Extraction size limit exceeded');
  }

  await writeFile(entry.path, uncompressed);
}

Why This Fix Works

The upgrade to 7.5.21 solves the vulnerability by:

  1. Preventing unbounded decompression: The library now rejects archives with abnormal compression ratios before consuming resources
  2. Enforcing resource limits: Maximum extraction sizes prevent memory exhaustion even if ratio checks are bypassed
  3. Fail-fast behavior: Suspicious archives are rejected immediately, not after resources are exhausted
  4. Maintaining compatibility: Valid tar.gz files continue to work normally—only malicious bombs are blocked

The changes in web/package-lock.json also updated the application version from 2.9.0 to 2.11.1, indicating this was part of a broader security update cycle.

Key Takeaways

  • node-tar 7.5.15 had no decompression ratio validation, allowing attackers to submit small archives that expanded to gigabytes and crashed the application
  • The harness-remote-web dependency tree exposed the application to CVE-2026-59873 through its package-lock.json configuration
  • Upgrading to tar 7.5.21 implements compression ratio monitoring and extraction size limits that detect and block gzip bombs before resource exhaustion
  • File size validation alone is insufficient—you must validate decompression ratios since gzip bombs are designed to have small compressed sizes
  • Defense in depth is essential: Combine library updates with input validation, resource limits, worker thread isolation, and runtime monitoring to protect against decompression attacks

How Orbis AppSec Detected This

  • Source: The vulnerable tar 7.5.15 dependency in web/package-lock.json, which could process untrusted archive files from user uploads, deployment packages, or external data sources
  • Sink: The tar.extract() and gunzip() operations that decompress archives without validating compression ratios or enforcing extraction size limits
  • Missing control: No decompression ratio validation, no maximum extraction size enforcement, and no resource consumption monitoring during archive processing
  • CWE: CWE-409 (Improper Handling of Highly Compressed Data / 'Zip Bomb')
  • Fix: Upgraded the tar dependency from version 7.5.15 to 7.5.21, which implements compression ratio checks and resource limits to detect and reject malicious gzip bombs

Orbis AppSec automatically detected this vulnerability and opened a pull request with the fix. Try Orbis AppSec on your repositories to find and fix issues like this automatically.

Conclusion

CVE-2026-59873 demonstrates how a single outdated dependency can expose your entire application to trivial Denial of Service attacks. The node-tar library's lack of decompression ratio validation in version 7.5.15 meant that any code path processing tar archives was vulnerable to gzip bomb attacks.

The fix—upgrading to tar 7.5.21—was straightforward but critical. The updated library implements multiple layers of protection: compression ratio monitoring, extraction size limits, and early termination for suspicious archives. These safeguards prevent attackers from weaponizing the compression algorithm against your application.

For developers, this vulnerability reinforces several key security principles: maintain up-to-date dependencies, implement defense in depth for file processing operations, and use static analysis tools to catch vulnerable dependencies before they reach production. A small dependency update can be the difference between a stable application and one that crashes from a single malicious upload.

Prevention and further reading

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #272

Related Articles

high

TrackOptionsManager DDL: Template-Literal SQL Injection Closed

The `TrackOptionsManager` service built its `CREATE TABLE` and `ALTER TABLE ... ADD COLUMN alias` statements by interpolating a `DEFAULT_ALIAS` constant directly inside single quotes in a JavaScript template literal, and its private `_query()` helper had no parameter channel at all. The fix routes the default value through `mysql.escape()` and gives `_query(q, params = [])` a real bound-parameter argument that is forwarded to `db.query()`. This removes an injection primitive on a schema-bootstra

critical

eval() in Async Function Constructor Enables Runtime Escape

The eval.mjs command handler used raw `eval()` to execute JavaScript expressions, creating a critical code injection path if owner credentials are compromised. The fix replaces `eval()` with the `AsyncFunction` constructor and explicitly shadows `process`, `require`, and other runtime globals as parameters, preventing evaluated code from reaching the Node.js runtime even when authentication boundaries fail.

high

How SQL injection via template literals happens in Node.js SQLite and how to fix it

A SQL injection vulnerability in `src/lib/codex-state.mjs` allowed dynamic column names to reach SQL queries through JavaScript template literals. The fix implements defense-in-depth with strict identifier validation using `SAFE_IDENTIFIER` regex before query construction.

high

How Denial of Service via Crafted ZIP File happens in Node.js and how to fix it

CVE-2026-39244 is a high-severity denial of service vulnerability in the adm-zip npm package that allows attackers to crash Node.js applications by uploading maliciously crafted ZIP files. The fix upgrades adm-zip from version 0.5.16 to 0.6.0, which adds proper memory bounds checking to prevent excessive allocation during archive extraction.

critical

How origin validation bypass happens in Express.js and how to fix it

A `POST /changeData` route in `src/main/server/routes/index.js` guarded state-changing writes with an origin allowlist, but the guard was wrapped in an `if (origin && ...)` truthiness check. Any request that simply omitted both `Origin` and `Referer` — a one-line `curl` command, a local script, a background process — skipped validation entirely and modified application data. The fix removes the truthiness short-circuit so a *missing* header is now treated as a rejection, not a pass.

critical

How CSRF vulnerabilities happen in Node.js API clients and how to fix them

A critical CSRF vulnerability in `lib/client.js` allowed attackers to forge authenticated POST requests to `/remote-ssh/api/*` endpoints. The fix adds the `X-Requested-With: XMLHttpRequest` header to enable proper CSRF token validation, blocking malicious cross-site requests with a minimal one-line change.