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 javascript.express.security.audit.express-check-csurf-middleware-usage.express-check-csurf-middleware-usage happens in Express.js and how to fix it

An Express.js application in `src/server.js` was missing CSRF (Cross-Site Request Forgery) protection middleware, leaving all state-changing endpoints vulnerable to forged requests from malicious sites. The fix introduces the `csrf` package to generate and validate tokens on non-GET requests, while exempting API-key-authenticated clients. This defensive hardening raises the bar against automated exploit chaining.

high

How Client-Side Denial of Service happens in Node.js FTP clients and how to fix it

CVE-2026-44240 is a client-side Denial of Service vulnerability in the `basic-ftp` Node.js package (versions prior to 5.3.1) caused by improper handling of unterminated multiline FTP server responses. An attacker controlling an FTP server—or capable of intercepting FTP traffic—could send a malformed response that causes the client to hang indefinitely. Upgrading `basic-ftp` to 5.3.1 and adding a package override in `package.json` closes the attack surface entirely.

high

How javascript.express.security.audit.express-check-csurf-middleware-usage.express-check-csurf-middleware-usage happens in Express.js and how to fix it

A publicly accessible Express.js API endpoint in `app/api/cameras.js` was missing CSRF protection, leaving state-changing requests (POST, PUT, DELETE, PATCH) vulnerable to cross-site request forgery attacks. The fix introduces Origin/Referer header validation middleware in `app/index.js` and removes a redundant Express instance from `cameras.js` that bypassed the application's middleware chain.

critical

How Command Injection via Unescaped Line Terminators Happens in Node.js and How to Fix It

A critical command injection vulnerability (CVE-2026-9277) was discovered in the shell-quote npm package version 1.8.3, where unescaped line terminators could allow attackers to execute arbitrary code. This fix upgrades shell-quote to version 1.9.0 using npm overrides to ensure all instances in the dependency tree are patched, eliminating the attack vector across the entire application.

critical

How Distributed Lock Takeover Happens in Node.js and How to Fix It

A critical vulnerability in `redis-lock/server.mjs` allowed any authenticated client to release another client's lock by guessing predictable holder identifiers like process IDs or hostnames. The fix implements cryptographically random `lockId` values that are minted on lock acquisition and validated on release, eliminating the exploit primitive entirely.

critical

How Server-Side Request Forgery (SSRF) happens in Node.js and how to fix it

A critical SSRF vulnerability was discovered in `fetch-worker.js` where URLs from `sources.txt` were fetched without any validation, allowing attackers to target internal services and cloud metadata endpoints. The fix implements a robust URL allowlist that enforces HTTPS and blocks requests to private IP ranges, localhost, and link-local addresses.