Back to Blog
critical SEVERITY8 min read

How Denial of Service via gzip bomb happens in Node.js tar and how to fix it

CVE-2026-59873 is a critical Denial of Service vulnerability in the `node-tar` package (versions before 7.5.19) that allows an attacker to trigger resource exhaustion by supplying a crafted gzip bomb archive. The fix upgrades `tar` from 7.5.16 to 7.5.19 in both `package.json` and `package-lock.json`, closing the attack surface for any Node.js application that processes tar archives. Because this package is used in production code — not just in tests — the exposure was real and immediate.

O
By Orbis AppSec
Published July 26, 2026Reviewed July 26, 2026

Answer Summary

CVE-2026-59873 is a Denial of Service vulnerability (CWE-400: Uncontrolled Resource Consumption) in the `node-tar` npm package affecting versions up to and including 7.5.16. An attacker can craft a malicious gzip bomb archive that, when decompressed by `node-tar`, causes unbounded memory or CPU consumption, crashing or freezing the Node.js process. The fix is to upgrade `tar` to version 7.5.19 or later, which adds decompression-size safeguards. In this repository the change was made by pinning `"tar": "^7.5.19"` in `package.json` and updating the corresponding integrity hash in `package-lock.json`.

Vulnerability at a Glance

cweCWE-400 (Uncontrolled Resource Consumption)
fixUpgrade node-tar from 7.5.16 to 7.5.19, which introduces decompression limits that reject oversized payloads
riskAn attacker who can supply a tar archive causes the server process to exhaust memory or CPU, resulting in downtime
languageNode.js / JavaScript
root causenode-tar 7.5.16 does not enforce an upper bound on decompressed data size when processing gzip-compressed archives
vulnerabilityDenial of Service via crafted gzip bomb (CVE-2026-59873)

How Denial of Service via gzip bomb happens in Node.js tar and how to fix it


The Vulnerability at a Glance

Field Detail
Vulnerability Denial of Service via crafted gzip bomb
CVE CVE-2026-59873
CWE CWE-400 — Uncontrolled Resource Consumption
Package node-tar (npm)
Affected version 7.5.16 (and earlier in the 7.x line)
Fixed version 7.5.19
Severity Critical

Introduction

The package-lock.json file in this repository pinned node-tar at version 7.5.16 — a version that contains a critical Denial of Service flaw catalogued as CVE-2026-59873. The Trivy scanner flagged the exact integrity hash for that version:

"integrity": "sha512-56adEpPMouktRlBLXiaYFFzZ/3+JXa8P9n7WbR+ibIjtviN55mEaOkiysCnPnWm+7kkui1Dn8J9l+g6zV8731w=="

Because tar is listed under dependencies (not devDependencies) in package.json, this library ships in the production bundle. Any Node.js process that calls into node-tar to extract an archive — whether that's unpacking a plugin, processing a user upload, or handling a build artifact — is exposed to this attack while the vulnerable version is installed.


The Vulnerability Explained

What is a gzip bomb?

A gzip bomb (sometimes called a "zip of death") is a compressed archive that is tiny on disk but expands to an enormous amount of data when decompressed. The classic example is a file that is a few kilobytes compressed but decompresses to gigabytes of repeated bytes. The attack exploits the mathematical properties of the DEFLATE compression algorithm, which can represent long runs of identical bytes with extreme efficiency.

How CVE-2026-59873 works in node-tar

node-tar uses Node.js's built-in zlib module to decompress gzip streams before parsing the TAR format. In versions up to and including 7.5.16, the decompression pipeline does not enforce an upper bound on how many bytes can be emitted from the decompressor. The relevant code path looks roughly like this (simplified pseudocode representing the vulnerable pattern):

// Vulnerable pattern in node-tar ≤ 7.5.16 (conceptual illustration)
const gunzip = zlib.createGunzip();
inputStream.pipe(gunzip).pipe(tarParser);
// No byte-count check on gunzip output — an attacker controls
// how many bytes flow into tarParser

Because there is no decompression-size guard between the zlib.createGunzip() output and the TAR parser, an attacker who can supply a crafted .tar.gz file can cause the Node.js process to:

  1. Allocate large amounts of heap memory as the decompressed data streams in.
  2. Peg the CPU at 100% as the event loop tries to process the flood of decompressed chunks.
  3. Ultimately crash with an out-of-memory error or become completely unresponsive.

Concrete attack scenario

Suppose this application allows users to upload a .tar.gz plugin bundle, and the server calls node-tar to extract it:

const tar = require('tar');

app.post('/upload-plugin', async (req, res) => {
  // req.file.path is attacker-controlled
  await tar.extract({ file: req.file.path, cwd: './plugins' });
  res.send('Plugin installed');
});

With node-tar 7.5.16, an attacker uploads a 50 KB gzip bomb that decompresses to 10 GB. The tar.extract() call happily starts streaming decompressed data with no size limit. The Node.js process runs out of memory and crashes — taking down the entire application for every other user. Because the crash is triggered by a single HTTP request, this is trivially repeatable for sustained downtime.

Real-world impact

  • Availability: The Node.js process crashes or becomes unresponsive, causing a full service outage.
  • No authentication required: If any unauthenticated endpoint processes tar archives, the attack requires zero credentials.
  • Amplification ratio: A well-crafted gzip bomb can achieve compression ratios exceeding 1,000:1, meaning a 1 MB upload can exhaust gigabytes of server RAM.

The Fix

What changed

The fix is a targeted version bump in two files:

package.jsontar is explicitly pinned to a safe minimum:

-        "oxc-parser": "^0.140.0",
+        "oxc-parser": "^0.140.0",
+        "tar": "^7.5.19",
         "ws": "^8.19.0"

package-lock.json — the resolved version and integrity hash are updated to the patched release:

 "node_modules/tar": {
-    "version": "7.5.16",
-    "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.16.tgz",
-    "integrity": "sha512-56adEpPMouktRlBLXiaYFFzZ/3+JXa8P9n7WbR+ibIjtviN55mEaOkiysCnPnWm+7kkui1Dn8J9l+g6zV8731w==",
+    "version": "7.5.19",
+    "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.19.tgz",
+    "integrity": "sha512-4LeEWl96twnS2Q7Bz4MGqgazLqO+hJN63GZxXoIqh1T3VweYD997gbU1ItNsQafqqXTXd5WFyFdReLtwvRBNiw==",

Why both files must change

  • package.json: Adding "tar": "^7.5.19" as an explicit top-level dependency ensures that even if another package in the dependency tree requests an older version of tar, npm's deduplication logic will resolve to 7.5.19 or newer. Without this entry, a transitive dependency could silently pull in the vulnerable 7.5.16.
  • package-lock.json: The lock file records the exact resolved URL and SHA-512 integrity hash. Updating the integrity hash to the one for 7.5.19 ensures that npm ci (used in CI/CD pipelines) installs the verified, patched binary and rejects any tampered or downgraded package.

What node-tar 7.5.19 actually fixes

Version 7.5.19 introduces decompression size accounting in the gzip pipeline. The patched version tracks the number of bytes emitted by the decompressor and aborts extraction if that count exceeds a configurable (and safe default) threshold. This means even a perfectly crafted gzip bomb is stopped before it can exhaust system resources.


Prevention & Best Practices

1. Keep dependencies locked and audited

Always commit your package-lock.json and run npm audit as part of your CI pipeline. A single npm audit --audit-level=critical step would have caught CVE-2026-59873 before it reached production.

# Add to your CI pipeline
npm audit --audit-level=critical

2. Use a software composition analysis (SCA) scanner

Tools like Trivy, Snyk, and GitHub Dependabot continuously monitor your lock files against known CVE databases. This vulnerability was caught by Trivy's CVE-2026-59873 rule scanning package-lock.json.

# Example: run Trivy against your repo
trivy fs --scanners vuln .

3. Enforce decompression limits in your own code

Even with a patched library, apply defense-in-depth by limiting the size of archives you accept before decompression:

const MAX_ARCHIVE_BYTES = 100 * 1024 * 1024; // 100 MB

app.post('/upload-plugin', upload.single('archive'), async (req, res) => {
  if (req.file.size > MAX_ARCHIVE_BYTES) {
    return res.status(413).send('Archive too large');
  }
  await tar.extract({ file: req.file.path, cwd: './plugins' });
  res.send('Plugin installed');
});

Note: checking the compressed size does not prevent a gzip bomb — you need library-level decompression limits (provided by node-tar ≥7.5.19) in addition to upload size checks.

4. Pin transitive dependencies explicitly

If a library you depend on uses tar internally, that transitive dependency may resolve to a vulnerable version unless you override it explicitly in package.json (as this fix does). Use npm ls tar to audit which version is actually installed:

npm ls tar
# Should show: tar@7.5.19

5. Security standards reference


Key Takeaways

  • node-tar 7.5.16 has no decompression size limit — a single crafted .tar.gz file can crash a Node.js process regardless of how the rest of the application is hardened.
  • Checking the compressed file size is not enough — gzip bombs are small when compressed; protection must happen at the decompression layer, which is what 7.5.19 provides.
  • Both package.json and package-lock.json must be updated — updating only the lock file leaves the door open for transitive resolution to pull in the vulnerable version on the next npm install.
  • Production dependencies vs. devDependencies matters — because tar was in dependencies, this vulnerability was live in the deployed application, not just in the developer's build environment.
  • SCA scanners catch what code review misses — no human reviewer inspecting application logic would notice a version number buried in package-lock.json; automated scanning is essential for dependency security.

How Orbis AppSec Detected This

  • Source: The package-lock.json file, which records the exact resolved version (7.5.16) and integrity hash of the node-tar package installed in the production dependency tree.
  • Sink: Any call to tar.extract(), tar.list(), or related node-tar APIs that processes a gzip-compressed archive — the decompression pipeline in node-tar 7.5.16 has no byte-count ceiling.
  • Missing control: No decompression size limit in the zlib pipeline inside node-tar 7.5.16; the library streams decompressed bytes to the TAR parser without checking how many bytes have been emitted.
  • CWE: CWE-400 — Uncontrolled Resource Consumption.
  • Fix: The tar package was upgraded from 7.5.16 to 7.5.19 in both package.json and package-lock.json, replacing the vulnerable integrity hash with the verified hash of the patched release.

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 dependency libraries are just as dangerous as logic flaws in your own code. A single outdated entry in package-lock.json"version": "7.5.16" — was enough to expose every archive-processing code path in this application to a resource-exhaustion attack requiring no authentication and no special knowledge of the application's internals.

The fix is surgical: two files changed, two version strings and one integrity hash updated. But the protection it provides is significant — node-tar 7.5.19 closes the decompression-size loophole that made the gzip bomb attack possible. Pair that with automated SCA scanning in your CI pipeline, explicit top-level dependency pinning, and upload-size guards in your own code, and you have a robust, layered defense against this entire class of attack.

Keep your lock files up to date. Scan them automatically. And never trust compressed input.


References

Frequently Asked Questions

What is a gzip bomb Denial of Service vulnerability?

A gzip bomb is a maliciously crafted compressed file that expands to a vastly larger size when decompressed. When a vulnerable library like node-tar processes it without size limits, the process consumes all available memory or CPU and crashes.

How do you prevent gzip bomb DoS in Node.js tar processing?

Always use a patched version of node-tar (≥7.5.19), enforce decompression size limits in your own code, and never decompress attacker-controlled archives without resource guards such as stream size caps or process-level memory limits.

What CWE is associated with this gzip bomb vulnerability?

CWE-400 — Uncontrolled Resource Consumption. The library fails to cap the amount of memory or CPU allocated during decompression, allowing a small input to trigger disproportionate resource usage.

Is input validation alone enough to prevent gzip bomb attacks?

No. Checking the compressed file size before decompression is insufficient because a gzip bomb is small when compressed. You need decompression-time size limits, which is exactly what node-tar 7.5.19 adds.

Can static analysis detect this kind of vulnerability?

Yes — software composition analysis (SCA) scanners like Trivy, Snyk, and Dependabot flag known-vulnerable package versions in package-lock.json. Trivy's CVE-2026-59873 rule detected this specific issue in the lock file.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #59

Related Articles

high

How IPv4-mapped IPv6 addresses bypass rate limiting in Express.js and how to fix it

A critical vulnerability in express-rate-limit versions prior to 8.2.2 allowed attackers to bypass per-client rate limiting on dual-stack servers by exploiting incorrect IPv6 subnet masking. When IPv4 clients connected through IPv4-mapped IPv6 addresses (like ::ffff:192.0.2.1), the library failed to properly identify unique clients, enabling unlimited requests that could lead to denial of service. The fix upgrades express-rate-limit to 8.2.2 and its dependency ip-address to 10.1.0, implementing

high

How Denial of Service via Unbounded Brace Expansion happens in Node.js and how to fix it

The brace-expansion library in Node.js contained a critical denial-of-service vulnerability where specially crafted input could trigger unbounded array expansion, consuming all available memory and crashing the process. This vulnerability affected multiple versions across the library's version branches. The fix upgrades brace-expansion to patched versions that implement strict limits on intermediate array sizes.

critical

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

A critical SSRF vulnerability (CVE-2026-69192) was discovered in the ip-address npm package version 10.2.0, which could allow attackers to bypass IP address validation and access internal services. The fix upgrades the dependency to version 10.3.1, which properly handles edge cases in IP address parsing that previously allowed trust-boundary bypasses.

critical

How Server-Side Request Forgery happens in Node.js CLI tools and how to fix it

A critical Server-Side Request Forgery (SSRF) vulnerability in the compass-guarded-transfer CLI tool allowed attackers to make HTTP requests to internal services and cloud metadata endpoints. The `normalizeInput` function in `run-transfer.mjs` validated that URLs started with "https://" but failed to prevent requests to private IP ranges like AWS metadata (169.254.169.254) or localhost, enabling potential credential theft and internal network reconnaissance.

critical

How Insufficient Origin Validation Happens in Express.js and How to Fix It

A critical security vulnerability in the `/changeData` endpoint allowed any remote attacker to modify user data without authorization. The Express.js route handler accepted requests from any origin and passed user-supplied data directly to the `changeData()` function. The fix implements origin validation using a regex pattern to restrict requests to trusted local sources only.

critical

How Missing Authorization Checks Happen in Node.js WhatsApp Bots and How to Fix Them

A critical authorization bypass was discovered in `plugins/tools-delete.js` where the delete command handler lacked an admin privilege check, allowing any WhatsApp group member to delete arbitrary messages. The fix adds `handler.admin = true` to enforce that only group administrators can invoke the delete functionality, preventing unauthorized message deletion by unprivileged users.