Back to Blog
critical SEVERITY4 min read

CVE-2026-59873: node-tar 7.5.11 DoS via Crafted Gzip Bomb

node-tar versions 7.5.11 through 7.5.18 are vulnerable to a denial-of-service attack through maliciously crafted gzip archives that decompress to disproportionately large sizes. An attacker can exploit this to exhaust memory and CPU resources by submitting a small, highly compressed archive that expands beyond configured limits during extraction.

O
By Orbis AppSec
•Technically reviewed by Anupam Mediratta•Published October 10, 2026•Reviewed October 10, 2026

Answer Summary

node-tar versions 7.5.11 through 7.5.18 are affected. An attacker can cause unbounded memory growth and CPU exhaustion by supplying a gzip-compressed tar archive that expands to many times its compressed size. The fix upgrades tar to 7.5.19, which introduces decompression ratio limits. CWE is unknown.

Vulnerability at a Glance

cweN/A
fixUpgrade to tar 7.5.19 with built-in decompression limits
riskMemory exhaustion and service unavailability from small malicious inputs
languageJavaScript (Node.js)
root causeMissing bounds on gzip decompression ratio during tar extraction
vulnerabilityDenial of Service via Gzip Bomb

A critical vulnerability in the tar npm package—versions 7.5.11 through 7.5.18—allows attackers to mount denial-of-service attacks using crafted gzip archives. These "gzip bombs" exploit the disparity between compressed and decompressed sizes: a few kilobytes of compressed data can expand to gigabytes, overwhelming memory and CPU resources during extraction. The fix, released in tar 7.5.19, introduces defensive limits on decompression ratios.

This issue is particularly insidious because it exploits a fundamental property of compression algorithms rather than a coding error. The tar package's automatic detection of gzip-compressed archives and its stream-based processing pipeline made it an ideal target for resource exhaustion attacks in CI/CD pipelines, package managers, and file upload handlers.

Affected Versions

Affected >= 7.5.11, <= 7.5.18
Fixed in 7.5.19
Ecosystem npm
CVE / GHSA CVE-2026-59873 / not assigned
CWE unknown

The Vulnerability Explained

The tar package provides streaming archive extraction with automatic format detection. When encountering a .tar.gz file or gzip-compressed stream, it pipes input through zlib's Gunzip transform without enforcing upper bounds on the output-to-input size ratio.

An attacker crafts a small archive—perhaps 10KB compressed—that decompresses to 10GB or more. The classic pattern uses repeated identical data (like null bytes), achieving extreme compression ratios. When tar processes this:

// Vulnerable pattern in tar 7.5.11
// Automatic gzip detection triggers unbounded decompression
const tar = require('tar')
await tar.x({ file: 'archive.tar.gz', cwd: '/tmp' })
// Memory unbounded until OOM kill

The tar.x() function, along with tar.t() and stream constructors, all share this vulnerable decompression path. The file option and stream inputs both trigger automatic format detection, which instantiates a Gunzip stream without ratio checking.

Real-world impact is severe for services that accept user uploads or process third-party archives: container registries, package mirrors, build systems, and deployment pipelines. A single malicious upload can crash worker processes, trigger container restarts, or exhaust memory quotas in serverless environments.

The Fix

Version 7.5.19 introduces decompression guards by tracking the ratio between compressed bytes read and uncompressed bytes produced. When this ratio exceeds a safe threshold, tar throws a TAR_BAD_ARCHIVE error and terminates processing.

The upgrade changes the overrides entry in package.json:

-      "tar": "7.5.11",
+      "tar": "7.5.21",

And correspondingly in the lockfile:

-  tar@7.5.11:
-    resolution: {integrity: sha512-Chj...}
+  tar@7.5.21:
+    resolution: {integrity: sha512-Xdht...}
     engines: {node: '>=18'}

The fix works by instrumenting the gzip decompression stream with byte counters. Before yielding each chunk of decompressed data, tar compares cumulative output against cumulative input. If outputBytes > inputBytes * MAX_RATIO (with a conservative default), processing halts immediately.

This approach preserves streaming efficiency for legitimate archives while bounding worst-case resource consumption. The error is catchable, allowing applications to log and reject malicious uploads gracefully rather than crashing.

Key Takeaways

  • Automatic format detection is a double-edged sword: tar's seamless handling of .tar.gz, .tar.bz2, and compressed streams improves developer experience but creates implicit trust boundaries that attackers can exploit.

  • Compression ratios must have configurable caps: Any system accepting compressed input from untrusted sources should enforce maximum expansion ratios. The tar 7.5.19 default of approximately 100:1 accommodates virtually all legitimate use cases.

  • Stream processing doesn't imply unbounded processing: Even stream-based APIs can exhaust resources if they lack backpressure and ratio limits. The vulnerability existed in streaming code, not synchronous buffering.

  • Dependency overrides require active maintenance: This fix arrived through a manual overrides entry in package.json, not a direct dependency. Transitive dependency trees hide vulnerable versions; explicit overrides need periodic review.

How Orbis AppSec Detected This

Source: The file parameter passed to tar.x() or tar.t() functions, or any readable stream piped to tar's extract transform.

Sink: The internal Gunzip stream instantiation in tar's Parse class, invoked when magic bytes indicate gzip compression.

Missing control: No validation of decompression ratio before or during the transformation; no maxReadSize or similar option enforced during automatic format detection.

CWE: unknown

Fix: Upgraded tar from 7.5.11 to 7.5.19, which adds automatic decompression ratio limits that throw catchable errors on gzip bomb detection.

Orbis AppSec detected this vulnerability automatically. Try Orbis AppSec on your repositories to find and fix issues like this.

Conclusion

CVE-2026-59873 demonstrates how compression algorithms, when used without safeguards, become attack vectors for resource exhaustion. The tar package's automatic gzip handling—normally a convenience feature—became a liability when confronted with pathological inputs. The 7.5.19 fix restores safety without sacrificing the streaming API's ergonomics, but it serves as a reminder that any system accepting compressed data from external sources must implement defense-in-depth through ratio limits, memory caps, and processing timeouts.

Prevention and further reading

Frequently Asked Questions

Does the tar 7.5.19 fix require code changes, or is it automatic?

The protection is automatic once upgraded. tar 7.5.19 enforces internal decompression limits without requiring callers to pass new options, though you may configure stricter limits via `maxReadSize` if desired.

Which specific tar API methods are affected by CVE-2026-59873?

The vulnerability affects any code path that processes gzip-compressed archives, including `tar.x()` (extract), `tar.t()` (list), and stream-based operations that auto-detect and decompress gzip input.

Is the 7.5.11 to 7.5.19 upgrade breaking for existing tar usage?

No breaking changes affect typical usage. The only behavioral change is that archives exceeding safe decompression ratios now throw a catchable error instead of consuming unbounded resources.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #37

Related Articles

high

MapManager.get() Race Condition Duplicates API Requests

The MapManager's `get(mapUid, cache)` method used a check-then-act pattern that permitted multiple concurrent requests to pass the cache miss check simultaneously, triggering redundant API calls and risking cache corruption. The fix introduces a `_pending` promise map to deduplicate in-flight fetches for identical map UIDs.

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.

critical

Go ArticleRemove() SQL Injection via fmt.Sprintf IN Clause

The Go backend's `ArticleRemove` function built a SQL `DELETE` statement by joining a caller-supplied slice of article IDs directly into the query string with `fmt.Sprintf`. Because the `aids` values came straight from the frontend with no validation or escaping, an attacker could inject arbitrary SQL into the `IN(...)` clause. The fix replaces string concatenation with a parameterized query using placeholders and a `DB.Exec` argument list.