Back to Blog
critical SEVERITY8 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` npm package (versions before 7.5.19) that allows an attacker to crash or exhaust a Node.js process by supplying a crafted gzip bomb archive. The fix upgrades `tar` from 7.5.16 to 7.5.19 in `frontend/package-lock.json`, closing the decompression resource exhaustion vector without affecting valid archive processing.

O
By Orbis AppSec
Published August 26, 2026Reviewed August 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 prior to 7.5.19. A remote attacker can craft a gzip bomb — a small, highly compressed archive that expands to enormous size — and supply it to any code path that calls `node-tar` to extract or inspect archives, causing the Node.js process to exhaust memory or CPU and become unresponsive. The fix is to upgrade the `tar` package from 7.5.16 to 7.5.19 in `frontend/package-lock.json` and `frontend/package.json`, which introduces decompression size limits that reject maliciously oversized payloads before they can consume server resources.

Vulnerability at a Glance

cweCWE-400 (Uncontrolled Resource Consumption)
fixUpgrade tar dependency from 7.5.16 to 7.5.19, which enforces decompression expansion limits
riskAn attacker can crash or hang the frontend build pipeline or server process by submitting a crafted archive
languageJavaScript / Node.js
root causenode-tar 7.5.16 did not enforce limits on decompressed output size when extracting gzip-compressed archives
vulnerabilityDenial of Service via Gzip Bomb (Decompression Bomb)

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


Vulnerability at a Glance

Field Detail
CVE CVE-2026-59873
Severity Critical
Package tar (node-tar) 7.5.16 → 7.5.19
CWE CWE-400: Uncontrolled Resource Consumption
Impact Process crash / memory exhaustion (Denial of Service)
Fixed in frontend/package-lock.json, frontend/package.json

Introduction

The frontend/package-lock.json file in this project pins the tar npm package to version 7.5.16 — a version that contains a critical Denial of Service flaw. Any code path in the frontend toolchain that calls node-tar to extract or inspect a .tar.gz archive is vulnerable to a gzip bomb attack: an attacker supplies a tiny, hyper-compressed archive that, when decompressed by node-tar, expands to a volume large enough to exhaust the Node.js process's available memory or CPU time, rendering the service unresponsive.

This is not a theoretical edge case. Gzip bombs are trivially crafted with standard tools and have been used to take down build systems, CI pipelines, and upload processors for years. The fix — upgrading tar to 7.5.19 — is a single-line dependency bump with zero behavioral change for legitimate archives.


The Vulnerability Explained

What Is a Gzip Bomb?

A gzip bomb (also called a decompression bomb) exploits the nature of compression algorithms. Highly repetitive data compresses with extreme efficiency. A file containing 1 GB of repeated null bytes might compress to just a few kilobytes. When a decompressor naively expands it without any size ceiling, it consumes gigabytes of memory in seconds.

The attack chain for this CVE looks like this:

Attacker crafts malicious .tar.gz
        
        
Attacker delivers archive to application
(upload endpoint, build artifact, package fetch, etc.)
        
        
Application calls node-tar 7.5.16 to extract/inspect archive
        
        
node-tar decompresses gzip stream with no expansion limit
        
        
Memory / CPU exhaustion  process crash  Denial of Service

The Vulnerable Dependency

In frontend/package-lock.json, the locked version was:

"node_modules/tar": {
  "version": "7.5.16",
  "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.16.tgz",
  ...
}

node-tar 7.5.16 does not enforce a maximum decompressed byte limit when processing gzip streams inside .tar.gz archives. The decompression loop continues until the stream is exhausted — or until the host OS runs out of memory.

A Concrete Attack Scenario

Imagine the frontend build pipeline accepts a .tar.gz package as part of a dependency fetch or a user-uploaded asset bundle. An attacker uploads the following (conceptual) bomb:

# Craft a gzip bomb: 1 byte of input → ~10 GB of output
python3 -c "import gzip, sys; sys.stdout.buffer.write(gzip.compress(b'\x00' * 10_000_000_000))" \
  > bomb.tar.gz

When node-tar 7.5.16 attempts to list or extract bomb.tar.gz, it enters the decompression loop and attempts to buffer 10 GB of null bytes. The Node.js heap grows until the process is killed by the OS OOM killer or the V8 heap limit is hit — either way, the service crashes.

Even in a CI/CD context (where the tar package is used by build tooling rather than a live server), a successful gzip bomb can hang a build job indefinitely, consuming runner minutes and blocking deployments.


The Fix

What Changed

The fix upgrades tar from 7.5.16 to 7.5.19 in both frontend/package.json and frontend/package-lock.json. Version 7.5.19 introduces a hard limit on the number of bytes that the gzip decompressor will emit before aborting with an error, preventing runaway memory consumption.

The package-lock.json diff also includes several "peer": true metadata corrections — these are lockfile housekeeping changes that npm made while resolving the updated dependency tree and do not affect runtime behavior:

-      "peer": true,
       "dependencies": {
         "@ampproject/remapping": "^2.2.0",

These peer flag removals indicate that npm re-evaluated which packages are true peer dependencies vs. direct dependencies during the upgrade resolution. They are cosmetic from a security standpoint but confirm that the full dependency graph was re-resolved cleanly against 7.5.19.

Before vs. After

Before (vulnerable):

"node_modules/tar": {
  "version": "7.5.16",
  "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.16.tgz",
  "integrity": "sha512-<old-hash>"
}

After (fixed):

"node_modules/tar": {
  "version": "7.5.19",
  "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.19.tgz",
  "integrity": "sha512-<new-hash>"
}

Why This Specific Change Solves the Problem

node-tar 7.5.19 adds a decompressed byte counter inside the gzip extraction pipeline. Once the running total of decompressed bytes crosses a configurable (and safe default) threshold, the library throws an error and halts decompression. This means:

  • A 1 KB gzip bomb that would expand to 100 GB is rejected early, after only a bounded number of bytes are written.
  • Legitimate archives of normal size are completely unaffected — the limit is set far above any real-world archive size encountered in typical frontend tooling.
  • The fix is backwards-compatible: no API changes, no configuration required, no code changes needed in the application layer.

Prevention & Best Practices

1. Pin and Audit Dependencies Regularly

Lockfiles like package-lock.json are your first line of defense. Keep them up to date and run npm audit (or a dedicated scanner like Trivy) in CI on every pull request:

# In your CI pipeline
npm audit --audit-level=critical

2. Enforce Decompression Limits in Your Own Code

If you write code that decompresses archives, never trust the decompressed size. Apply limits explicitly:

const MAX_DECOMPRESSED_BYTES = 500 * 1024 * 1024; // 500 MB
let totalBytes = 0;

gunzipStream.on('data', (chunk) => {
  totalBytes += chunk.length;
  if (totalBytes > MAX_DECOMPRESSED_BYTES) {
    gunzipStream.destroy(new Error('Decompression limit exceeded'));
  }
});

3. Validate Archive Sources

Never extract archives from untrusted sources without validation. If your application accepts user-uploaded archives:

  • Check the compressed size before decompression (reject anything suspiciously small that claims to be large).
  • Run extraction in an isolated process or container with memory limits enforced at the OS level (e.g., --memory in Docker).
  • Use a timeout on extraction operations.

4. Use Automated Dependency Scanning

Tools that caught this vulnerability:

Tool How It Helps
Trivy Scans package-lock.json against CVE databases, flagged this exact issue
npm audit Built-in Node.js advisory check
Dependabot / Renovate Automated PRs for dependency upgrades
Snyk Deep dependency tree analysis with exploit context

5. Security Standards Reference

  • CWE-400: Uncontrolled Resource Consumption — the root cause classification for this vulnerability.
  • OWASP A05:2021 – Security Misconfiguration: Outdated or unpatched dependencies fall under this category.
  • OWASP Dependency-Check: A tool specifically designed to identify known vulnerable components.

Key Takeaways

  • node-tar versions before 7.5.19 have no decompression size limit — any code path that calls tar.extract() or tar.list() on attacker-controlled input is vulnerable to memory exhaustion.
  • Compressed file size is not a reliable safety signal — a 1 KB .tar.gz can contain gigabytes of decompressed data; always limit decompressed output, not input.
  • The frontend/package-lock.json lockfile is a security artifact, not just a reproducibility tool — stale versions in the lockfile can introduce critical vulnerabilities even when package.json uses a permissive semver range.
  • Trivy's scan of package-lock.json caught this CVE before it reached production, demonstrating the value of scanning the full resolved dependency tree (not just direct dependencies).
  • The upgrade from 7.5.16 → 7.5.19 is a zero-risk change for valid workloads — the decompression limit in 7.5.19 only rejects pathologically oversized payloads that no legitimate archive would produce.

How Orbis AppSec Detected This

  • Source: The tainted input enters via any .tar.gz archive processed by the node-tar library — in this project's context, this includes archives fetched during the frontend build process (npm package tarballs, build artifacts, uploaded assets).
  • Sink: The dangerous call site is node-tar's internal gzip decompression pipeline (GunzipStream handler in node-tar ≤7.5.16), invoked whenever tar.extract(), tar.list(), or tar.parse() processes a compressed archive.
  • Missing control: node-tar 7.5.16 lacked a maximum decompressed byte limit. There was no ceiling on how many bytes the gzip stream could emit before the library accepted the data as valid archive content.
  • CWE: CWE-400 — Uncontrolled Resource Consumption. The library consumed unbounded memory proportional to the decompressed output of attacker-controlled input.
  • Fix: The tar package was upgraded from 7.5.16 to 7.5.19 in frontend/package-lock.json and frontend/package.json, enabling the built-in decompression size guard introduced in 7.5.19.

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 compression libraries are critical infrastructure risks, not minor annoyances. A single malicious archive, routed through an unpatched node-tar, can bring down a Node.js process regardless of how well the rest of the application is hardened. The fix is as simple as a version bump — but finding that version bump before an attacker exploits it requires continuous, automated dependency scanning integrated into your development workflow.

Keep your lockfiles fresh, scan your full dependency tree (not just direct dependencies), and enforce resource limits whenever your code touches user-influenced compressed data.


References

Frequently Asked Questions

What is a gzip bomb vulnerability?

A gzip bomb is a specially crafted compressed file that is tiny on disk but expands to an enormous size when decompressed. If a library like node-tar decompresses it without size limits, the process exhausts memory or CPU, causing a Denial of Service.

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

Use an up-to-date version of node-tar (≥7.5.19) that enforces decompression size limits, validate archive sizes before processing, and avoid extracting untrusted archives without resource caps.

What CWE is a gzip bomb / decompression bomb vulnerability?

CWE-400: Uncontrolled Resource Consumption. The system fails to limit the resources consumed while processing attacker-controlled input.

Is checking the compressed file size enough to prevent a gzip bomb?

No. A gzip bomb's power comes from the ratio between compressed and decompressed size. A 1 MB file can decompress to hundreds of gigabytes. You must enforce limits on the *decompressed* output, not just the input size.

Can static analysis detect gzip bomb vulnerabilities?

Yes. Tools like Trivy scan dependency manifests (package-lock.json) against known CVE databases and can flag vulnerable versions of node-tar before they reach production, as demonstrated in this fix.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #730

Related Articles

high

How Dependabot Missing Cooldown happens in GitHub Actions and how to fix it

A high-severity misconfiguration in `.github/dependabot.yml` left this Node.js library without a cooldown period, meaning Dependabot would immediately propose updates to newly published packages — including potentially malicious or unstable ones. The fix adds a `cooldown` block with `default-days: 7` to both the `npm` and `github-actions` package ecosystem entries, introducing a mandatory 7-day waiting period before any new package version is surfaced as an update candidate.

critical

How CSRF Protection Failures Happen in FastAPI and How to Fix Them

A critical CORS misconfiguration in `backend/main.py` allowed cookies to be sent alongside wildcard-origin requests, violating the CORS specification and opening the door to cross-site request forgery attacks. The fix conditionally disables `allow_credentials` when the allowed origins list contains a wildcard, bringing the configuration into compliance with browser security rules. This change closes a subtle but dangerous gap that could have let attackers on sibling subdomains forge authenticate

critical

How Missing Rate Limiting Happens in Node.js SSE Handlers and How to Fix It

A critical missing rate-limiting control in `src/sse/handlers/chat.js` allowed any caller to flood the SSE chat endpoint with unlimited requests, risking server resource exhaustion, denial of service, and runaway AI provider API costs. The fix introduces a per-IP sliding-window rate limiter that caps requests at 60 per minute and returns HTTP 429 on violations. Because the endpoint was publicly reachable and only validated API keys — not request frequency — exploitation required nothing more tha

medium

How Denial of Service via Catastrophic Backtracking happens in Node.js and how to fix it

CVE-2026-4867 is a Denial of Service vulnerability in path-to-regexp 0.1.12 where malformed URL parameters can trigger catastrophic backtracking in the library's regular expression engine, allowing an attacker to hang or crash a Node.js application with a single crafted request. The fix upgrades path-to-regexp to version 0.1.13, which patches the vulnerable regex patterns. This change was applied via a package-level override to ensure the patched version is used throughout the entire dependency

high

How Denial of Service via Exponential-Time Complexity happens in Node.js and how to fix it

CVE-2026-13149 is a high-severity Denial of Service vulnerability in the `brace-expansion` npm package, where crafted input strings trigger exponential-time processing that can freeze or crash a Node.js application. The fix upgrades `brace-expansion` from `2.0.2` to `2.1.4` and `minimatch` from `5.1.6` to `5.1.9`, along with npm `overrides` to ensure the patched versions are used throughout the entire dependency tree.

critical

How Unrestricted File Upload happens in Node.js/Express and how to fix it

A critical unrestricted file upload vulnerability was discovered in `mainsystem/routes/admin/profile.js`, where the avatar upload endpoint accepted any file type without validation. An authenticated attacker could upload a malicious server-side script to a web-accessible directory and execute arbitrary code on the server. The fix adds MIME type filtering, an allowlist of safe image formats, and a 2 MB file size limit to the multer middleware.