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

critical

How supply chain code injection happens in Node.js build scripts and how to fix it

A critical supply chain vulnerability in the chatgpt-auto-continue extension's build utility allowed arbitrary code execution by fetching JavaScript from a CDN without integrity verification. The fix implements SHA-256 hash validation before executing the downloaded code, preventing potential supply chain attacks through compromised CDN content or man-in-the-middle attacks.

critical

How hardcoded default credentials happen in Node.js database initialization and how to fix it

A critical vulnerability was discovered in `hubcmdui/database/database.js` where the database initialization routine hardcoded the default admin credentials (`root` / `admin@123`) and logged them in plaintext. Because these credentials are visible in the public source code, any attacker who finds the repository can immediately authenticate as an administrator on any unpatched deployment. The fix removes the plaintext credential from the log message, and operators are now prompted to change the d

high

How command injection happens in Node.js child_process and how to fix it

A high-severity command injection vulnerability was discovered in `bootstrap.js` at line 34, where the `exec()` function was used to run shell commands constructed from a `folder` variable. By replacing `exec()` with `execFile()` and passing arguments as an array, the fix eliminates the shell interpolation entirely, closing the door on command injection attacks that could have affected all downstream consumers of this Node.js library.

high

How SSRF and Credential Leakage via Absolute URLs happens in axios and how to fix it

A high-severity vulnerability (CVE-2025-27152) in axios versions prior to 1.8.2 allowed Server-Side Request Forgery (SSRF) attacks and credential leakage when making HTTP requests with absolute URLs. This vulnerability was fixed by upgrading from axios 1.7.4 to 1.8.2 in both package.json and package-lock.json, eliminating the attack vector that could have exposed authentication tokens and enabled unauthorized server-side requests.

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 library that allows attackers to crash FTP clients by sending malformed, unterminated multiline FTP responses. Upgrading from version 5.0.5 to 5.3.1 patches this critical flaw that could have disrupted any application using the vulnerable library for FTP operations.

critical

How WebSocket protocol length header abuse happens in Node.js and how to fix it

A critical vulnerability (CVE-2026-54466) in websocket-driver versions prior to 0.7.5 allows attackers to corrupt WebSocket messages by manipulating protocol length headers. This can lead to data integrity issues, denial of service, or potentially arbitrary code execution in affected Node.js applications. The fix involves upgrading the websocket-driver dependency to version 0.7.5.