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.


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.


Prevention and further reading

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #59

Related Articles

high

How Denial of Service via Infinite Loop Happens in JavaScript Dependencies and How to Fix It

CVE-2026-67213 is a high-severity denial of service vulnerability in nanoid before version 5.1.6 that triggers an infinite loop during random ID generation when processing specially crafted input. We upgraded nanoid across the entire dependency tree to patch this flaw and prevent attackers from freezing application threads. This fix ensures that ID generation remains resilient even when handling adversarial input patterns.

high

How Sensitive Data Exposure happens in Zotero plugins and how to fix it

A high-severity data exposure vulnerability in `Zotero.ts` automatically transmitted complete document metadata—including private notes, attachment paths, and tags—to external LLM services without user consent. The fix replaces broad `item.toJSON()` serialization with explicit field selection, sending only essential bibliographic data.

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.