Back to Blog
critical SEVERITY7 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 the node-tar package (versions before 7.5.19) where a crafted gzip bomb can exhaust server resources during archive extraction. The fix upgrades the `tar` dependency from version 7.5.11 to 7.5.21 and pins it via a `package.json` overrides entry to prevent transitive re-introduction of the vulnerable version. Left unpatched, any code path that processes untrusted `.tar.gz` files could be weaponized to bring down a Node.js service.

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

Answer Summary

CVE-2026-59873 is a critical Denial of Service vulnerability (CWE-400) in the node-tar npm package where a specially crafted gzip bomb — a tiny compressed file that expands to enormous size — can overwhelm memory and CPU when extracted, crashing a Node.js application. The vulnerability exists in node-tar versions prior to 7.5.19. The fix is to upgrade the `tar` package to 7.5.21 in `package-lock.json` and add a `"overrides": { "tar": "7.5.21" }` entry in `package.json` to ensure no transitive dependency can silently pull in the vulnerable version.

Vulnerability at a Glance

cweCWE-400 (Uncontrolled Resource Consumption)
fixUpgrade tar to 7.5.21 and pin the version in package.json overrides to prevent transitive re-introduction
riskAn attacker can crash or hang a Node.js server by supplying a malicious compressed archive
languageJavaScript / Node.js
root causenode-tar 7.5.11 lacks decompressed-size limits when processing gzip streams, allowing unbounded memory/CPU expansion
vulnerabilityDenial of Service via crafted gzip bomb

How Denial of Service via Gzip Bomb Happens in Node.js and How to Fix It

The Threat Hidden in Your package-lock.json

Every Node.js project that processes compressed archives — uploads, build artifacts, package installs — is only as safe as the libraries doing the decompression. When Trivy scanned this project's package-lock.json, it found tar pinned at version 7.5.11: a version vulnerable to CVE-2026-59873, a critical Denial of Service flaw triggered by a crafted gzip bomb.

The fix — upgrading to 7.5.21 and locking the version via package.json overrides — is small in diff size but significant in impact. This post unpacks exactly what the vulnerability is, how an attacker would exploit it, and what every Node.js developer should take away.


The Vulnerability Explained

What Is a Gzip Bomb?

A gzip bomb is a compressed archive engineered to have an extreme compression ratio. The canonical example is a file a few kilobytes in size that decompresses into gigabytes of data. The compression format itself is legitimate — the bomb exploits the absence of decompression size limits in the consuming library.

When node-tar 7.5.11 receives a .tar.gz stream, it pipes the gzip-compressed bytes through a decompressor and then processes the resulting tar entries. In the vulnerable version, there is no enforced ceiling on how many decompressed bytes the gzip layer is allowed to produce. An attacker who can supply a crafted archive to a code path using node-tar can therefore cause:

  • Memory exhaustion: the decompressed buffer grows until the Node.js heap is full and the process crashes or is OOM-killed.
  • CPU starvation: the event loop is blocked processing an ever-expanding decompression stream, making the server unresponsive to legitimate requests.

The Vulnerable Package Entry

Before the fix, package-lock.json contained:

"node_modules/tar": {
  "version": "7.5.11",
  "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.11.tgz",
  "integrity": "sha512-ChjMH33/KetonMTAtpYdgUFr0tbz69Fp2v7zWxQfYZX4g5ZN2nOBXm1R2xyA+lMIKrLKIoKAwFj93jE/avX9cQ=="
}

And in the legacy dependencies section:

"tar": {
  "version": "7.5.11",
  "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.11.tgz",
  "integrity": "sha512-ChjMH33/KetonMTAtpYdgUFr0tbz69Fp2v7zWxQfYZX4g5ZN2nOBXm1R2xyA+lMIKrLKIoKAwFj93jE/avX9cQ=="
}

Both entries point to the same vulnerable tarball. Any code in the dependency tree that calls tar.extract(), tar.x(), or any streaming extraction API from this package inherits the flaw.

A Concrete Attack Scenario

Consider a common pattern in Node.js build tools or file-processing services:

const tar = require('tar');

// User-supplied archive path or piped upload stream
await tar.x({
  file: userSuppliedArchivePath,
  cwd: '/tmp/workspace'
});

An attacker crafts a .tar.gz file where the gzip layer compresses, say, 500 MB of null bytes down to ~50 KB. They upload this file or supply it as a build artifact. When the server calls tar.x(), node-tar 7.5.11 begins decompressing without limit. Within seconds, the Node.js process has consumed all available memory, the heap crashes, and the service goes down — a classic Denial of Service with no authentication required beyond the ability to supply a file.

Because the vulnerability is in the decompression layer (before tar entries are even parsed), no amount of post-extraction validation helps. The damage is done during the read.


The Fix

Upgrading the Dependency

The fix involves three coordinated changes across two files.

Change 1 — node_modules/tar in package-lock.json:

-  "version": "7.5.11",
-  "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.11.tgz",
-  "integrity": "sha512-ChjMH33/KetonMTAtpYdgUFr0tbz69Fp2v7zWxQfYZX4g5ZN2nOBXm1R2xyA+lMIKrLKIoKAwFj93jE/avX9cQ==",
+  "version": "7.5.21",
+  "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.21.tgz",
+  "integrity": "sha512-XdhtCvlMywwxpCW8YEq3lOXBJpUPTR2OHHcwLPO3HwsJqOHa2Ok/oJ7ruGzp+JrKoRPVCzJwAdEjqLW/vNRPHA==",

Change 2 — legacy dependencies.tar entry in package-lock.json:

-  "version": "7.5.11",
+  "version": "7.5.21",

Both the node_modules/tar block (used by npm v7+ for the flat install) and the legacy nested dependencies block are updated. Updating only one would leave the other as a potential resolution source depending on the npm version and install flags used in the CI pipeline.

Change 3 — package.json overrides:

+  "overrides": {
+    "tar": "7.5.21"
+  }

This is the most important defensive layer. npm's overrides field forces every package in the dependency tree — direct or transitive — to resolve tar to exactly 7.5.21. Without this, a future npm install or a transitive dependency update could silently pull tar@^7.5.4 (the range that was previously specified) back to a vulnerable patch version.

Note also the pinning change in the transitive dependency block:

-  "tar": "^7.5.4",
+  "tar": "7.5.21",

The caret (^) range was replaced with an exact version, eliminating the window where a semver-compatible but vulnerable release could be resolved.

Why 7.5.21 Instead of 7.5.19?

The PR title references 7.5.19 as the first fixed version (per the CVE advisory), but the actual resolved version in the diff is 7.5.21. This is correct practice: when a patch series is available, pinning to the latest patch in the series picks up any additional correctness or security fixes that landed after the initial CVE patch, without introducing breaking changes (patch versions are semver-compatible).


Prevention & Best Practices

1. Always Set overrides for Security-Critical Dependencies

The overrides field in package.json is your last line of defense against transitive dependency vulnerabilities. When a CVE is fixed in a library, add an override immediately so that no part of your dependency tree can resolve the vulnerable version:

"overrides": {
  "tar": "7.5.21"
}

For Yarn users, the equivalent is resolutions.

2. Run Dependency Audits in CI

Integrate npm audit or a dedicated scanner (Trivy, Snyk, Dependabot) into your CI pipeline. This vulnerability was caught by Trivy scanning package-lock.json — a step that costs nothing to add to a GitHub Actions workflow:

- name: Security audit
  run: npx trivy fs --exit-code 1 --severity CRITICAL,HIGH .

3. Validate and Limit Archive Processing

Where your application logic allows it, add upstream controls before calling tar.x():

  • File size limit: reject archives above a reasonable threshold before extraction begins.
  • Content-Type validation: verify the MIME type server-side, not just client-supplied headers.
  • Sandboxed extraction: run extraction in a subprocess with memory limits (--max-old-space-size) or in a container with cgroup memory constraints.

These controls don't replace the library fix but provide defense-in-depth.

4. Pin Exact Versions for Security-Sensitive Packages

Semver ranges like ^7.5.4 are convenient but dangerous for security-sensitive packages. Consider pinning exact versions for libraries that handle untrusted data (archive extraction, image processing, XML parsing) and automating version bumps via Dependabot or Renovate with mandatory review.

5. Understand CWE-400

This vulnerability is classified under CWE-400: Uncontrolled Resource Consumption. The OWASP guidance on this class of vulnerability recommends:

  • Imposing limits on all resource-consuming operations that process external input.
  • Treating compressed data as untrusted even when the compression format itself is standard.
  • Monitoring resource usage in production to detect anomalous consumption early.

Key Takeaways

  • tar@7.5.11 in package-lock.json is exploitable: any code path calling tar.x() or tar.extract() with attacker-controlled input could crash the Node.js process via a crafted gzip bomb.
  • Updating package-lock.json alone is insufficient: without the overrides entry in package.json, a future npm install can re-introduce a vulnerable version through transitive dependencies that specify tar: "^7.5.4".
  • The ^ semver operator is a liability for security patches: replacing "tar": "^7.5.4" with "tar": "7.5.21" closes the resolution window that allowed the vulnerable version to persist.
  • Decompression attacks bypass post-extraction controls: validating extracted file contents does not help — the DoS occurs during the gzip decompression phase, before any tar entry is parsed.
  • Trivy's static analysis of package-lock.json is effective: this vulnerability was detected without running the application, demonstrating the value of scanning lockfiles as part of every CI build.

How Orbis AppSec Detected This

  • Source: Untrusted compressed archive data entering any code path that calls tar.x(), tar.extract(), or the streaming tar.Parse() API — potentially from HTTP file uploads, build artifact downloads, or piped stdin.
  • Sink: The gzip decompression layer inside node_modules/tar (version 7.5.11), which processes the compressed stream without enforcing a maximum decompressed-size limit.
  • Missing control: No decompressed-byte ceiling in the gzip stream handler, allowing unbounded memory and CPU consumption before any application-level validation can run.
  • CWE: CWE-400 — Uncontrolled Resource Consumption.
  • Fix: Upgraded tar from 7.5.11 to 7.5.21 in package-lock.json and added "overrides": { "tar": "7.5.21" } in package.json to prevent transitive re-introduction of the 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 reminder that Denial of Service vulnerabilities in compression libraries are not theoretical — they are practical, low-effort attacks that require no authentication and produce immediate, visible impact. The node-tar gzip bomb flaw in version 7.5.11 could be triggered by anyone who can supply a file to your application, making it especially dangerous in any service that processes user uploads, CI artifacts, or third-party packages.

The fix is straightforward: upgrade to 7.5.21, pin the version in package.json overrides, and integrate lockfile scanning into your CI pipeline so future regressions are caught before they reach production. Small changes in dependency management hygiene have an outsized effect on your application's resilience against this class of attack.


References

Frequently Asked Questions

What is a gzip bomb vulnerability?

A gzip bomb is a maliciously crafted compressed file that decompresses to a disproportionately large size (sometimes gigabytes from kilobytes), exhausting memory or CPU and causing a Denial of Service.

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

Use a patched version of node-tar (≥7.5.19) that enforces decompression size limits, and pin the version with package.json overrides to prevent transitive downgrades.

What CWE is a gzip bomb Denial of Service?

CWE-400 — Uncontrolled Resource Consumption, which covers scenarios where an application fails to limit the resources consumed when processing untrusted input.

Is validating file extensions enough to prevent gzip bomb attacks?

No. File extension checks are trivially bypassed. Proper mitigation requires the extraction library itself to enforce decompressed-size limits during streaming, as implemented in node-tar ≥7.5.19.

Can static analysis detect gzip bomb vulnerabilities?

Yes. Vulnerability scanners like Trivy can detect known-vulnerable package versions in package-lock.json and flag them against CVE databases, which is exactly how CVE-2026-59873 was found here.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #2811

Related Articles

high

How Denial of Service via Unbounded Intermediate Arrays happens in JavaScript and how to fix it

CVE-2026-69152 is a high-severity Denial of Service vulnerability in the `brace-expansion` npm package (versions prior to 1.1.18/2.1.4/3.0.6/5.0.9) that allows attackers to crash a Node.js application by crafting glob patterns that generate unbounded intermediate arrays, effectively bypassing the earlier CVE-2026-14257 mitigation. The fix upgrades `brace-expansion` from 1.1.14 to 1.1.18 in `frontend/package-lock.json`, closing the bypass and restoring safe memory bounds during pattern expansion.

high

How Quadratic CPU Consumption happens in JavaScript YAML parsing and how to fix it

A high-severity denial-of-service vulnerability (GHSA-5p4m-2wfm-xmqj) was discovered in js-yaml affecting both the 3.x and 4.x branches, where parsing YAML documents containing `!!omap` tags triggers quadratic CPU consumption. The fix upgrades js-yaml from `^4.1.1` to `5.2.0` in the project's GitHub Actions workflow dependencies, closing the attack surface for any untrusted YAML input processed by CI/CD tooling.

critical

How Missing Rate Limiting happens in Express.js and how to fix it

Two public API endpoints in `server.js` — `/api/health` and `/api/contact` — were exposed without any rate limiting middleware, allowing attackers to exhaust server resources or spam an SMTP server with unlimited requests. The fix adds rate limiting to both endpoints, with stricter controls on the resource-intensive `/api/contact` route that triggers email sending operations. This change closes a directly exploitable denial-of-service vector in a production web service.

high

How Denial of Service via Specific Input Sequence happens in JavaScript (marked) and how to fix it

CVE-2026-41680 is a high-severity Denial of Service vulnerability in the marked Markdown parsing library, affecting versions prior to 18.0.2. By supplying a crafted input sequence to the parser, an attacker can cause the application to hang or exhaust resources, making the frontend unavailable. Upgrading marked from 18.0.0 to 18.0.2 in both `package.json` and `package-lock.json` closes the vulnerability without affecting valid Markdown rendering.

high

How Quadratic CPU Consumption happens in JavaScript YAML parsing and how to fix it

A high-severity denial-of-service vulnerability in js-yaml (GHSA-5p4m-2wfm-xmqj) caused quadratic CPU consumption when resolving `!!omap` YAML types in both the 3.x and 4.x branches. The fix upgrades js-yaml from 3.14.2 to 3.15.1 and from 4.1.1 to 4.3.1, eliminating the algorithmic complexity exploit while leaving all valid YAML inputs unaffected.

high

How Denial of Service via Unbounded Data Happens in JavaScript and how to fix it

CVE-2025-58754 is a high-severity Denial of Service vulnerability in the popular axios HTTP client library, caused by the absence of a data size check on incoming response or request payloads. An attacker who can influence the size of data processed by axios could exhaust server memory or CPU, bringing down dependent Node.js applications. The fix upgrades axios from version 1.8.4 to 1.18.0, closing the unbounded data processing path.