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
•Technically reviewed by Anupam Mediratta•Published July 26, 2026•Reviewed 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.json — tar 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

critical

Lampa Desktop Auto-Update Heuristic Bypass: Execution of Unverified

Lampa Desktop's auto-update mechanism downloaded JavaScript and CSS from `raw.githubusercontent.com` using only heuristic validation—file size thresholds and string pattern matching—that attackers could trivially satisfy. The fix introduces cryptographic integrity verification by cross-referencing Git blob hashes from the GitHub Contents API, ensuring downloaded code matches the repository's authoritative state before execution.

high

adm-zip 0.6.0 Preserves SUID Bits From ZIPs: CVE-2026-102282

The `adm-zip` dependency resolved to 0.6.0 in this project's dependency tree, a version affected by CVE-2026-102282: during extraction it applies the Unix permission bits stored in each ZIP entry's external file attributes verbatim, including the setuid (`04000`), setgid (`02000`), and sticky bits. An attacker who controls an archive passed to `extractAllTo()` or `extractEntryTo()` can therefore have the extractor create a setuid binary owned by whatever user the extraction process runs as. The

high

requestInput() Type Confusion: NaN and Object Bypass in JavaScript

The `requestInput()` utility function lacked validation on its `type` parameter and failed to handle `NaN` results from float conversions, creating a type confusion weakness. An attacker could supply malformed inputs that propagate unhandled `NaN` values or unexpected object types through the type system. The fix adds explicit guards against `NaN` type parameters and rejects non-primitive type values.

critical

No Rate Limit on /api/uploads/presign Enables DoS

The `/api/uploads/presign` endpoint accepted unlimited concurrent requests to generate storage presigned URLs, giving an attacker a free lever to exhaust storage-provider quotas and server resources. The fix adds an `express-rate-limit` middleware capping each client to 30 requests per minute on that route.

high

CVE-2026-54673: builder-util-runtime Leaks Auth Headers on Redirect

electron-updater and electron-builder rely on builder-util-runtime to fetch update manifests and artifacts over HTTP. A flaw in that shared HTTP executor allowed credential headers attached to the original update-feed request to be re-sent after a redirect, exposing them to any host the redirect pointed to. The project fixes this by upgrading builder-util-runtime to 9.7.0 and collapsing a duplicate, older copy of the package that electron-updater had pinned on its own.

high

image-size 1.2.1 DoS: Zero-Valued Dimensions in Image Buffer Parser

A high-severity denial-of-service vulnerability in image-size 1.2.1 allows attackers to crash Node.js services using malicious image buffers with zero-valued dimensions. The fix removes the vulnerable `queue` dependency and tightens dimension validation in version 2.0.3.