Back to Blog
critical SEVERITY7 min read

How Denial of Service via Gzip Bomb happens in Node.js and how to fix it

A critical Denial of Service vulnerability (CVE-2026-59873) in the `tar` npm package allowed attackers to craft malicious gzip archives that could exhaust memory or CPU during decompression. The fix upgrades `tar` from 7.5.11 to 7.5.21 across `package.json` and `package-lock.json`, closing the resource-exhaustion path without changing any application code.

O
By Orbis AppSec
Published September 7, 2026Reviewed September 7, 2026

Answer Summary

CVE-2026-59873 is a Denial of Service vulnerability (CWE-409, Improper Handling of Highly Compressed Data) in the Node.js `tar` package, where a maliciously crafted gzip archive ("gzip bomb") could cause uncontrolled memory or CPU consumption during decompression. The fix is a dependency upgrade from `tar` 7.5.11 to 7.5.21 in `package.json` and `package-lock.json`, which patches the decompression logic to enforce safe limits on expanded output size.

Vulnerability at a Glance

cweCWE-409 (Improper Handling of Highly Compressed Data)
fixUpgrade the `tar` dependency to 7.5.21 in `package.json` overrides and `package-lock.json`
riskUncontrolled memory/CPU consumption when extracting untrusted `.tar.gz` archives, leading to process crash or service unavailability
languageJavaScript / Node.js
root cause`tar` versions ≤7.5.11 lacked adequate guardrails against maliciously compressed gzip streams during decompression
vulnerabilityDenial of Service via crafted gzip bomb

Introduction

The package-lock.json file in this repository locks in the exact versions of every dependency your project resolves at install time — including tar, a package used (directly and transitively, via node-gyp and prebuild-install) to extract .tar and .tar.gz archives during npm installs and build steps. A flaw in how tar version 7.5.11 handled gzip decompression created a real risk: a specially crafted, highly compressed archive — a "gzip bomb" — could be fed into the extraction pipeline and cause the process to consume excessive memory or CPU, effectively taking down whatever service or build process was unpacking it.

This is CVE-2026-59873, rated critical, and it lived quietly in the dependency tree until Trivy's scanner flagged the exact version string 7.5.11 sitting in three separate places inside package-lock.json: the top-level node_modules/tar entry, the node-gyp sub-dependency block, and the legacy tar resolution entry used by older npm lockfile formats. Anyone building or installing this project was pulling in the vulnerable decompression logic without knowing it.

The Vulnerability Explained

tar is one of the most widely used low-level archive libraries in the npm ecosystem — it's a transitive dependency of node-gyp, prebuild-install, and countless native-module build chains. When it processes an archive, it typically streams the file through gzip decompression before parsing the tar entries themselves.

Before the fix, the lockfile pinned this exact vulnerable version:

"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 the project's overrides block explicitly pinned it too:

"overrides": {
  "tar": "7.5.11",
  ...
}

That overrides entry is important: it means every consumer of tar in the dependency graph — including node-gyp and prebuild-install, which both list "tar": "7.5.11" in their own requires blocks — was forced onto the vulnerable release, even if a nested dependency wanted a newer, safer version.

The underlying issue with this version of tar is that its gzip decompression path did not adequately bound the amount of work or memory allocated for a highly compressed input stream. A gzip bomb exploits the enormous compression ratio achievable with repetitive data: a payload of a few kilobytes can decompress into gigabytes of output, or force the decompressor into pathological CPU behavior while expanding it.

Attack scenario: Imagine this project's CI pipeline, or an install script, or any code path that calls tar.extract() on a file uploaded by a user or fetched from an untrusted URL (a common pattern for plugin systems, artifact repositories, or package installers built on node-gyp/prebuild-install). An attacker submits a tiny .tar.gz file — say 50KB — crafted so that its gzip stream expands to tens of gigabytes when decompressed. The vulnerable tar 7.5.11 begins decompressing it without sufficient limits, memory usage balloons, and the Node.js process either OOMs and crashes or becomes unresponsive to legitimate requests. Because tar extraction is often triggered automatically (e.g., during npm install of a package with native bindings via node-gyp), this attack surface extends beyond direct application code into the build/install tooling itself — a single malicious tarball published or proxied through a compromised registry mirror could disrupt every developer and CI runner that installs the package.

The Fix

The fix, delivered by OrbisAI Security, is a targeted dependency upgrade — no application logic needed to change because the vulnerability lives entirely inside the tar package's decompression internals.

Before:

"tar": "7.5.11",

resolved from https://registry.npmjs.org/tar/-/tar-7.5.11.tgz

After:

"tar": "7.5.21",

resolved from https://registry.npmjs.org/tar/-/tar-7.5.21.tgz

The change touches exactly the places you'd expect for a clean dependency bump:

  1. package.json — the overrides.tar entry was bumped from "7.5.11" to "7.5.21", ensuring the entire dependency tree (including node-gyp and prebuild-install, which both declare tar as a dependency) resolves to the patched version rather than being force-pinned to the vulnerable one.
  2. package-lock.json — all three lockfile records for tar were updated in lockstep:
    - The top-level node_modules/tar block (version, resolved URL, and integrity hash)
    - The node-gyp package's nested "tar": "7.5.11""7.5.21" requirement
    - The legacy tar resolution entry (used for npm's older dependency-tree format) with a fresh integrity hash

Because the integrity hash changes alongside the version and URL, npm will verify the new package contents cryptographically on install — there's no risk of a stale or tampered artifact silently slipping through under the old hash.

This is a case where "the fix" is really "trust the upstream maintainers' patch." Version 7.5.21 of tar includes the hardening needed to safely bound decompression work against maliciously compressed input, so simply pulling in that version — and making sure the overrides block doesn't force everyone back down to 7.5.11 — eliminates the exposure without any behavioral change for legitimate archives.

Prevention & Best Practices

  • Keep decompression/archive libraries current. Packages like tar, zlib, unzipper, and yauzl sit on a security-sensitive attack surface (parsing untrusted binary formats) and should be tracked closely with automated dependency updates (Dependabot, Renovate, or a tool like Orbis AppSec).
  • Audit your overrides/resolutions blocks. A pinned override can accidentally keep a vulnerable transitive dependency alive even after you've "upgraded" — as seen here, node-gyp and prebuild-install were both silently forced onto tar@7.5.11 by the project's own overrides entry.
  • Never extract untrusted archives without resource limits. If your application code calls tar.extract(), zlib.gunzip(), or similar on user-supplied or externally-fetched files, wrap it with explicit memory/time budgets (e.g., streaming size counters, maxSize options where supported, or running extraction in a resource-constrained subprocess/container).
  • Run dependency vulnerability scanning in CI. This exact issue was caught by Trivy scanning package-lock.json — integrate SCA (Software Composition Analysis) tooling into your pipeline so vulnerable lockfile entries are flagged before merge, not after.
  • Reference CWE-409 and CWE-400 when threat-modeling archive handling. Decompression bombs are a well-known class of resource-exhaustion attack; design any archive-processing feature assuming the input is adversarial.

Key Takeaways

  • The vulnerable tar 7.5.11 was pinned in three places in package-lock.json plus the package.json overrides block — a single missed spot would have left the fix incomplete.
  • overrides in package.json can inadvertently force vulnerable versions onto transitive dependencies like node-gyp and prebuild-install, so they must be updated in the same PR as the direct dependency.
  • Gzip bombs exploit the same decompression code paths used by routine npm install and build tooling — this isn't just an "application input" risk, it's a supply-chain/build-pipeline risk too.
  • The integrity hash in package-lock.json changes with the version bump, so npm will cryptographically verify you're actually getting the patched tar@7.5.21 package contents, not a stale cache.
  • No application code changes were required — this is a textbook example of why fast dependency patching matters more than custom mitigation code for library-level CVEs.

How Orbis AppSec Detected This

  • Source: Any untrusted .tar.gz archive passed into the tar package's extraction/decompression APIs — whether from user uploads, external URLs, or transitive install flows through node-gyp/prebuild-install
  • Sink: The gzip decompression routine inside tar@7.5.11's extraction logic
  • Missing control: No bound on decompressed output size/CPU work when processing a highly compressed (gzip bomb) input stream
  • CWE: CWE-409 (Improper Handling of Highly Compressed Data), related to CWE-400 (Uncontrolled Resource Consumption)
  • Fix: Upgraded tar from 7.5.11 to 7.5.21 in package.json (overrides) and package-lock.json, pulling in upstream hardening against maliciously compressed archives

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 bugs don't always live in your application code — sometimes they're baked into the low-level archive-handling libraries every Node.js project depends on for something as routine as npm install. Because tar 7.5.11 was pinned not just as a direct dependency but forced via overrides onto node-gyp and prebuild-install as well, a single stale version string in package-lock.json created a critical, exploitable resource-exhaustion path. The fix — bumping to tar@7.5.21 everywhere it's referenced — closes that gap cleanly, with zero behavioral impact on legitimate archives. Treat your lockfile like production code: scan it, patch it promptly, and double-check overrides/resolutions blocks whenever you bump a security-sensitive dependency.

References

Frequently Asked Questions

What is a gzip bomb Denial of Service vulnerability?

It's an attack where a small, maliciously crafted gzip-compressed file expands to an enormous size (or triggers excessive CPU work) when decompressed, exhausting memory or CPU and crashing or hanging the process handling it.

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

Keep decompression libraries like `tar` and `zlib` up to date, enforce maximum output size/time limits when decompressing untrusted input, and avoid extracting archives from unauthenticated sources without sandboxing or resource caps.

What CWE is associated with gzip bomb Denial of Service?

CWE-409 (Improper Handling of Highly Compressed Data), often paired with CWE-400 (Uncontrolled Resource Consumption).

Is upgrading the vulnerable package alone enough to prevent this Denial of Service?

For this specific CVE, the vendor patch in `tar` 7.5.21 is enough since the flaw is inside the library's decompression logic, but adding your own resource limits and timeouts is a good defense-in-depth practice for any archive-handling code.

Can static analysis detect this gzip bomb vulnerability?

Static analysis alone can't spot the flaw inside `tar`'s decompression algorithm, but dependency scanners (like the trivy rule that flagged CVE-2026-59873 here) can detect that a vulnerable version is present in your lockfile.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #97

Related Articles

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.

critical

How Remote Code Execution Happens in Handlebars Template Compilation and How to Fix It

CVE-2026-33937 is a critical remote code execution vulnerability in Handlebars.js that allows attackers to execute arbitrary code by passing maliciously crafted Abstract Syntax Tree (AST) objects to the compile() function. The vulnerability was patched in version 4.7.9, and we've upgraded to protect against this threat vector.

critical

How SQL Injection happens in PHP bulk email systems and how to fix it

A critical SQL injection vulnerability in `admin/utilities/bulkEmailSystem.php` allowed attackers to inject arbitrary SQL through unvalidated database names passed from user input. The fix implements strict input validation using regex pattern matching to ensure only safe database identifiers are processed, preventing exploitation of the bulk email functionality.