Back to Blog
critical SEVERITY8 min read

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

CVE-2026-59873 is a critical Denial of Service vulnerability in node-tar versions prior to 7.5.19, where a maliciously crafted gzip bomb can exhaust server resources when extracting archives. The fix upgrades the `tar` dependency from version 7.5.15 to 7.5.21 in `package-lock.json` and pins the version via an `overrides` block in `package.json`. Any application that processes user-supplied tar archives is at risk of resource exhaustion, making this an urgent upgrade.

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

Answer Summary

CVE-2026-59873 is a critical Denial of Service vulnerability (CWE-400: Uncontrolled Resource Consumption) in the Node.js `node-tar` package. In versions up to 7.5.15, a specially crafted gzip bomb — a tiny compressed file that expands to enormous size — can be fed to the tar extraction pipeline, causing memory and CPU exhaustion. The fix is to upgrade `tar` to version 7.5.21 (or at minimum 7.5.19) and pin it via an `overrides` block in `package.json` to prevent transitive dependency drift back to a vulnerable version.

Vulnerability at a Glance

cweCWE-400
fixUpgrade tar to 7.5.21 and pin the version with a package.json overrides block
riskAn attacker can crash or hang the server by supplying a malicious compressed archive
languageJavaScript / Node.js
root causenode-tar 7.5.15 lacks adequate decompression size limits, allowing unbounded memory expansion
vulnerabilityDenial of Service via Gzip Bomb

How Denial of Service via Gzip Bomb Happens in Node.js and How to Fix It

Vulnerability at a Glance

Field Detail
CVE CVE-2026-59873
Severity Critical
Package tar (node-tar)
Affected version 7.5.15 (and earlier)
Fixed version 7.5.19+ (upgraded to 7.5.21)
CWE CWE-400: Uncontrolled Resource Consumption
Attack type Denial of Service via crafted gzip bomb

Introduction

The package-lock.json file in this project locked the tar dependency at version 7.5.15 — a version that contains a critical flaw in its gzip decompression pipeline. When node-tar processes a compressed archive, it streams the decompressed data through a series of internal transforms. In vulnerable versions, there is no hard ceiling on how much data those transforms are allowed to produce. A single HTTP request carrying a few kilobytes of compressed payload can silently instruct the server to allocate gigabytes of memory, bringing the Node.js process — and everything running alongside it — to a halt.

This is the essence of CVE-2026-59873: an attacker does not need credentials, elevated privileges, or insider knowledge. They only need to reach any code path that calls into node-tar with attacker-controlled input.


The Vulnerability Explained

What Is a Gzip Bomb?

A gzip bomb (also called a "zip of death" or decompression bomb) exploits the asymmetry between compressed and uncompressed data. Legitimate gzip files typically compress at ratios of 2:1 to 10:1. A carefully constructed gzip bomb can achieve ratios of 1,000,000:1 or higher — a 10 KB file that decompresses to 10 GB.

The technique works by nesting layers of highly repetitive data, which gzip's DEFLATE algorithm compresses extremely efficiently. When the decompressor expands each layer, memory consumption grows exponentially.

Why node-tar 7.5.15 Is Vulnerable

The vulnerable version locked in package-lock.json was:

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

In this version, node-tar's internal gzip decompression stream does not enforce a maximum decompressed byte budget. The extraction pipeline reads compressed chunks, passes them through Node.js's built-in zlib.createGunzip() transform, and writes the resulting bytes into memory without checking whether the cumulative decompressed size has exceeded any reasonable threshold.

A Concrete Attack Scenario

Consider an application that accepts .tar.gz uploads — perhaps a build artifact uploader, a plugin installer, or a data import endpoint. An attacker crafts a gzip bomb:

  1. They create a file containing millions of repeated null bytes.
  2. They compress it with gzip, producing a ~50 KB file.
  3. They POST this file to the upload endpoint.
  4. The server calls tar.extract() on the uploaded stream.
  5. node-tar 7.5.15 begins decompressing: 50 KB → 500 MB → 5 GB → process OOM crash.

No authentication is required. No special privileges are needed. The attack is repeatable and can be automated. Even if the OS kills the Node.js process, the attacker can immediately repeat the request, effectively keeping the service offline indefinitely.

Real-World Impact for This Application

The PR notes that the vulnerable path is present in the dependency tree but not confirmed reachable — meaning the tar package is pulled in as a transitive dependency (likely through build tooling or a plugin system). Even transitive exposure matters: if any code path in the dependency tree calls tar.extract() or tar.parse() on user-supplied data, the application is exploitable. Given the critical severity rating, treating this as exploitable is the correct posture.


The Fix

What Changed

The fix makes two coordinated changes: upgrading the resolved version in package-lock.json and pinning the version in package.json via an overrides block.

package-lock.json — Version Upgrade

Before:

"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:

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

The new integrity hash (sha512-XdhtCvl...) cryptographically guarantees that npm installs exactly the patched binary — not a cached copy of the vulnerable version.

package.json — Overrides Block

Before:

{
  "devDependencies": {
    "@tauri-apps/cli": "^2.11.4"
  }
}

After:

{
  "devDependencies": {
    "@tauri-apps/cli": "^2.11.4"
  },
  "overrides": {
    "tar": "7.5.21"
  }
}

This is the more important of the two changes. Without the overrides block, the next npm install or npm update could silently resolve tar back to a vulnerable version if any transitive dependency specifies a loose version range like "tar": "^7.0.0". The overrides block hard-pins tar to 7.5.21 across the entire dependency tree, regardless of what individual packages request.

How the Patch Fixes the Problem

node-tar 7.5.19 introduced decompressed-size accounting in its gzip stream handling. The patched version tracks the total number of bytes produced by the decompressor and aborts extraction if that count exceeds a configurable — but sensibly defaulted — threshold. This means a 50 KB gzip bomb that would have expanded to 5 GB now causes a controlled error rather than a memory exhaustion crash.

The fix is backward-compatible: valid archives that stay within reasonable size bounds are unaffected. The PR description confirms: "it only tightens handling of untrusted input and leaves valid inputs unaffected."


Prevention & Best Practices

1. Always Pin Transitive Dependencies That Handle Archives

Don't rely on semver ranges alone for security-sensitive packages. Use npm overrides (npm 8.3+), yarn resolutions, or pnpm.overrides to enforce minimum safe versions across your entire dependency tree:

// package.json
"overrides": {
  "tar": ">=7.5.19"
}

2. Integrate Dependency Scanning Into CI/CD

Tools like Trivy, Snyk, npm audit, and OWASP Dependency-Check can catch vulnerable versions before they reach production. Add a step to your pipeline:

# Example: fail the build if any critical CVEs are found
trivy fs --exit-code 1 --severity CRITICAL .

3. Enforce Decompression Size Limits at the Application Layer

Even with a patched library, apply defense-in-depth. If your application extracts archives, add your own size checks:

const MAX_UNCOMPRESSED_BYTES = 500 * 1024 * 1024; // 500 MB

let totalBytes = 0;
tarStream.on('entry', (entry) => {
  entry.on('data', (chunk) => {
    totalBytes += chunk.length;
    if (totalBytes > MAX_UNCOMPRESSED_BYTES) {
      tarStream.destroy(new Error('Archive exceeds size limit'));
    }
  });
});

4. Never Extract Untrusted Archives With Default Settings

If your application accepts archive uploads from users, treat every archive as potentially malicious. Run extraction in a sandboxed worker process with memory limits:

# Node.js worker with a 256 MB heap limit
node --max-old-space-size=256 extract-worker.js

5. Monitor for Dependency Drift

Schedule regular npm audit runs and automated dependency update PRs (e.g., via Dependabot or Renovate) to catch newly disclosed CVEs quickly.

Relevant Standards

  • CWE-400: Uncontrolled Resource Consumption — https://cwe.mitre.org/data/definitions/400.html
  • OWASP A05:2021 – Security Misconfiguration covers failure to update and harden components
  • OWASP Dependency Check is the canonical tool reference for this class of issue

Key Takeaways

  • tar 7.5.15 in package-lock.json was the exact vulnerable artifact — even a transitive lock on this version is enough to expose your application to CVE-2026-59873.
  • Upgrading package-lock.json alone is insufficient — without the overrides block in package.json, the next npm install can silently reintroduce the vulnerable version through a transitive dependency's loose version range.
  • Gzip bombs are cheap to craft and devastating to unpatched servers — a ~50 KB file can consume gigabytes of memory, making this a high-leverage attack for any service that processes user-supplied archives.
  • The overrides pattern is the correct npm mechanism for enforcing a minimum safe version of a transitive dependency across an entire project, and should be part of every security fix for indirect dependencies.
  • Static analysis tools like Trivy can catch this class of vulnerability before it reaches production by scanning package-lock.json against the CVE database — integrate them into your CI pipeline now.

How Orbis AppSec Detected This

  • Source: The tainted data enters wherever user-supplied or network-fetched compressed archive data is passed to node-tar's extraction API (e.g., tar.extract() or tar.parse()).
  • Sink: node-tar's internal gzip decompression stream in node_modules/tar version 7.5.15, which performs unbounded decompression without a byte-count ceiling.
  • Missing control: No maximum decompressed-size limit was enforced in the tar extraction pipeline, allowing a crafted gzip bomb to exhaust process memory.
  • CWE: CWE-400 — Uncontrolled Resource Consumption.
  • Fix: The tar dependency was upgraded from 7.5.15 to 7.5.21 in package-lock.json, and a "overrides": { "tar": "7.5.21" } block was added to package.json to prevent transitive dependency resolution from reverting to a vulnerable version.

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 is a sharp reminder that Denial of Service vulnerabilities in archive-handling libraries are not theoretical. A single crafted gzip bomb — trivial to produce — can bring down a Node.js service running an unpatched version of tar. The fix here is precise and minimal: upgrade to 7.5.21 and pin the version with an overrides block to prevent regression. More broadly, any application that touches user-supplied compressed data should treat decompression as a resource-consumption risk and apply both library-level patches and application-level size guards. Keep your dependency tree shallow, your locks tight, and your scanners running on every commit.


References

Frequently Asked Questions

What is a gzip bomb vulnerability?

A gzip bomb is a maliciously crafted compressed file that is tiny on disk but expands to an enormous size when decompressed. If a library does not impose limits on decompressed output size, processing such a file can exhaust memory and CPU, causing a Denial of Service.

How do you prevent gzip bomb vulnerabilities in Node.js?

Keep archive-handling libraries like node-tar up to date, pin dependency versions using package.json overrides, and never extract user-supplied archives without size and depth limits.

What CWE is a gzip bomb / DoS vulnerability?

CWE-400: Uncontrolled Resource Consumption. It describes situations where a program does not properly control the amount of resources it allocates in response to an input.

Is input validation alone enough to prevent a gzip bomb attack?

No. Checking the compressed file size before extraction is insufficient because the compressed data is intentionally small. The library itself must enforce limits on the decompressed output size, which is what the patched version of node-tar does.

Can static analysis detect gzip bomb vulnerabilities?

Yes. Tools like Trivy scan dependency manifests such as package-lock.json against known CVE databases and can flag vulnerable package versions before they reach production, as demonstrated in this fix.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #4

Related Articles

high

How missing dependency update cooldowns happen in GitHub Dependabot configurations and how to fix it

A semgrep scan flagged `.github/dependabot.yml` for lacking a cooldown period, meaning Dependabot would immediately propose updates to brand-new package versions across npm, Bundler, and Docker ecosystems. The fix adds a `cooldown: default-days: 7` block to every `package-ecosystem` entry, forcing a one-week waiting period before newly published releases are considered — reducing exposure to malicious or unstable package drops.

high

How dependabot-missing-cooldown happens in GitHub Actions/Node.js and how to fix it

The repository's `.github/dependabot.yml` had no cooldown period configured, meaning Dependabot could immediately propose updates to newly published package versions with zero time for the community to flag malware or instability. The fix adds a `cooldown` block with `default-days: 7` to both the `npm` and `github-actions` ecosystems, forcing a 7-day waiting period before new releases are surfaced as update PRs.

high

How Path Traversal Happens in TensorFlow's Data Service and How to Fix It

TensorFlow's data service dispatcher validated dataset IDs against forward-slash traversal attacks but overlooked backslash characters on non-Windows platforms, allowing attackers to escape the root directory. A targeted fix adds explicit backslash validation across all platforms, closing a high-severity path traversal vulnerability in the snapshot management system.

critical

How Unbounded WebSocket Message Handling Causes Resource Exhaustion in Node.js and How to Fix It

The WebSocketCrossServerAdapter class in a popular Node.js WebSocket library lacked any rate limiting on inbound messages, allowing attackers to flood Redis nodes and WebSocket servers with high-volume traffic. The fix introduces a configurable `rateLimit` option that caps messages per connection per second, preventing resource exhaustion while preserving legitimate functionality.

critical

How Remote Code Execution Happens in Handlebars Template Compilation and How to Fix It

CVE-2026-33937 is a critical remote code execution vulnerability in Handlebars.js that allows attackers to execute arbitrary code by passing maliciously crafted Abstract Syntax Tree (AST) objects to the compile() function. The vulnerability was patched in version 4.7.9, and we've upgraded to protect against this threat vector.

critical

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

A critical Denial of Service vulnerability (CVE-2026-59873) in the `tar` npm package allowed attackers to craft malicious gzip archives that could exhaust memory or CPU during decompression. The fix upgrades `tar` from 7.5.11 to 7.5.21 across `package.json` and `package-lock.json`, closing the resource-exhaustion path without changing any application code.