Sep 29, 2026·8 min read·6 visits
A bypass of the decompression bomb protection in adm-zip (CVE-2026-39244) allows attackers to trigger out-of-memory crashes by setting the declared uncompressed size header of a malicious ZIP entry to 0, which disables zlib limits.
A critical denial-of-service vulnerability in the adm-zip npm package allows attackers to bypass decompression-bomb protections introduced in version 0.5.18. By declaring the uncompressed file size as exactly 0, an attacker can disable the maxOutputLength constraint in the Node.js zlib wrapper, leading to complete system memory exhaustion and process crashes.
The popular Node.js library adm-zip provides synchronous and asynchronous APIs to decompress ZIP archives directly in-memory. Applications integrate this library to process user-supplied archives, exposing a significant attack surface to remote untrusted inputs. When parsing an archive, adm-zip relies on metadata from the central directory and local headers to understand compression parameters and allocate buffers.
In earlier iterations of the library, specifically versions prior to 0.5.18, a critical vulnerability identified as CVE-2026-39244 existed. The parser eagerly pre-allocated memory using Buffer.alloc() based directly on the uncompressed size specified by the file headers. Because this value is attacker-controlled and unvalidated, processing a crafted archive containing an inflated size header (such as 4 gigabytes) caused immediate unrecoverable out-of-memory errors on the host application.
To remediate CVE-2026-39244, the developers introduced a validation mechanism in version 0.5.18 that leveraged Node.js's native zlib maxOutputLength constraint to abort decompression if the output exceeded the declared header size. However, a logic flaw in this patch led to the discovery of GHSA-RCW4-F5RP-G42V. By declaring an uncompressed file size of exactly zero, an attacker can completely disable this decompression limit, allowing high-ratio compression bombs to bypass all system resource constraints and trigger process-level denial-of-service.
The root cause of GHSA-RCW4-F5RP-G42V lies in the implementation of the validation logic within the inflater module. To construct the safety parameters for the underlying zlib library, adm-zip evaluated the declared size using a ternary check: version >= 15 && expectedLength > 0 ? { maxOutputLength: expectedLength } : {}. When processing an entry with a declared size of 0, the check expectedLength > 0 evaluated to false, leaving the options block empty and disabling the maxOutputLength constraint.
In the ZIP format, file entries can legitimately declare an uncompressed size of 0 to indicate empty files or directory placeholders. By exploiting this, an attacker can supply a fully-populated, high-ratio Deflate stream under a file record that claims to be empty. The library accepts the record as valid, bypasses the expectedLength safety check, and forwards the deflated data stream to Node's internal zlib engine without any output length restriction.
Additionally, the asynchronous processing pipeline in adm-zip failed to implement any level of stream-based safety limits. While the synchronous API is designed to respect options like maxOutputLength, Node's streaming APIs behave differently during sequential data emissions. The async path accumulated data chunks continuously in a list without cross-referencing the aggregate size against the expected limits, allowing arbitrary data inflation to occur unchecked.
This combination of logic bypasses highlights the difficulty of retrofitting memory limits on top of complex file parsers. By failing to enforce a minimal boundary or check actual stream data accumulation, the protection mechanism was entirely neutralized by a single byte change in the ZIP central directory header. The failure is classified under CWE-400 (Uncontrolled Resource Consumption) and CWE-697 (Incorrect Comparison).
The vulnerability transition becomes clear when examining the code changes in zipEntry.js and methods/inflater.js. In version 0.5.17, the library allocated buffers directly from the uncompressed size header, exposing the allocation path to instant crashes. The 0.5.18 patch removed this direct allocation for DEFLATED files and introduced the maxOutputLength option, but introduced the ternary expression that returned an empty object when the expected size was 0.
Below is the logic in methods/inflater.js before the fix for GHSA-RCW4-F5RP-G42V:
// Vulnerable logic in adm-zip 0.5.18 - 0.6.0
const option = version >= 15 && expectedLength > 0 ? { maxOutputLength: expectedLength } : {};If an attacker sets the uncompressed size field to 0, expectedLength is passed as 0. The parser returns {} for option, leaving the zlib engine with no limits.
In version 0.6.1, this logic was replaced with a secure floor and manual stream boundaries. The developer ensured that maxOutputLength is always set to at least 1, which prevents empty objects and forces zlib to abort if any data is decompressed from an entry that claims to be empty. The patch also introduced manual size accumulation checks to protect the asynchronous streaming paths.
Below is the patched logic implemented in methods/inflater.js for version 0.6.1:
// Patched logic in adm-zip 0.6.1
const maxOutputLength = expectedLength > 0 ? expectedLength : 1;
const option = version >= 15 ? { maxOutputLength } : {};Furthermore, the patch secured the stream data listener on the asynchronous path. By keeping an active count of decompressed chunks and calling a termination function if total > maxOutputLength, the parser enforces limits even when Node's native streaming APIs ignore maxOutputLength. This dual-layered validation ensures that both synchronous and asynchronous extraction paths are protected against inflated structures.
Exploiting GHSA-RCW4-F5RP-G42V requires minimal prerequisite access. The attack vector is entirely remote and unauthenticated, requiring only that the target system exposes an endpoint that processes user-supplied archives through adm-zip. The exploit utilizes a crafted ZIP file containing a single entry that specifies an uncompressed size of 0 while containing a highly compressed Deflate stream (a zip bomb).
To construct the payload, an attacker generates a large buffer of repeated characters (such as 1 gigabyte of null bytes) and compresses it using standard Deflate. This generates a small compressed stream, often less than 1 kilobyte. The attacker then parses the raw binary of the ZIP and modifies the uncompressed size field within both the Local File Header and the Central Directory File Header to 0x00000000, while preserving the compressed size field.
When the target application calls extraction functions like extractAllTo() or entry.getData(), adm-zip initializes the decompression routine. Because the uncompressed size is 0, the options block is initialized empty on vulnerable versions. The zlib engine decompressor consumes system memory until V8 exceeds its heap limit, terminating the Node.js process and causing a denial of service.
The security impact of GHSA-RCW4-F5RP-G42V is classified as High, presenting a severe risk of denial-of-service across impacted environments. Since Node.js is single-threaded, a blocking CPU-bound or memory-bound operation like uncontrolled decompression halts the event loop for all concurrent users before crashing the process. In multi-tenant systems or API gateways, a single malicious upload can disrupt service for all users on that instance.
Because V8 limits heap allocation (typically to 1.4 GB on older 64-bit platforms and up to 4 GB on modern runtimes), memory exhaustion occurs rapidly when decompressing billions of bytes. When memory limits are reached, Node.js is unable to allocate further buffers and terminates immediately with an uncatchable fatal error. The lack of standard error handling during such crashes prevents recovery, meaning system orchestrators (like Kubernetes or PM2) must detect and restart the container, leading to service degradation.
While this vulnerability does not directly expose application data or allow remote code execution, it remains a high-value target for adversaries seeking to cause disruption. Because the vulnerability requires no special privileges or authentication, any backend service accepting file inputs (such as profile images, document uploads, or database imports) is fully exposed to this denial-of-service vector.
Remediation requires upgrading the adm-zip dependency to version 0.6.1 or newer. This update ensures that the ternary logic enforces a minimum output cap of 1 byte for any entries declaring a size of zero, and implements explicit checks within the asynchronous stream reader to prevent runaway inflation.
While the fix in 0.6.1 is robust for modern Node.js environments, several structural edge cases must be evaluated by security teams. First, applications running on Node.js versions earlier than 15 will not benefit from the native maxOutputLength restriction on synchronous paths because the API option is not supported by legacy runtimes. Although the async path remains guarded by the manual length check, synchronous extractions on legacy runtimes will remain vulnerable.
Secondly, while individual file decompression is capped, adm-zip does not enforce aggregate limits across multi-file archives. An attacker can still supply an archive containing thousands of small, valid entries. Processing such an archive can still exhaust disk space or CPU cycles through directory traversal operations and file system overhead. Security teams must implement absolute processing limits, sandboxed execution environments, and maximum archive size limits at the network edge to ensure comprehensive defense-in-depth.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
adm-zip cthackers | >= 0.5.18 < 0.6.1 | 0.6.1 |
adm-zip cthackers | < 0.5.18 | 0.5.18 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-400 (Uncontrolled Resource Consumption) |
| Attack Vector | Network / Remote |
| CVSS Score | 7.5 (High) |
| Exploit Status | Proof of Concept (PoC) Available |
| KEV Status | Not Listed |
The software does not properly control the allocation and maintenance of a limited resource, enabling an attacker to influence the amount of resources consumed and leading to a denial of service.
A DOM-based Cross-Site Scripting (XSS) vulnerability exists in the Laravel exception debug page rendering pipeline when APP_DEBUG=true is active. This flaw allows an attacker to execute arbitrary client-side JavaScript in the security context of an authenticated user's session when they hover over interactive code-trace tooltips handled by Tippy.js.
An uncontrolled resource consumption vulnerability in the logs SDK of OpenTelemetry-Go allows remote attackers to trigger a denial of service. Under conditions of downstream exporter backpressure, the BatchingProcessor enters a tight loop, exhausting CPU resources. This occurs because the processor immediately schedules retry attempts without waiting for its ticker interval, spinning continuously when the internal queue remains filled above the batch size. The issue affects all versions prior to v0.21.0 of the go.opentelemetry.io/otel/sdk/log package.
CVE-2026-76844 is a high-severity path traversal vulnerability in webpack-dev-middleware affecting multiple version branches. It stems from an incomplete fix for CVE-2024-29180 when serving files via a physical filesystem with a non-slash-terminated publicPath configuration. Attackers can bypass directory validation to access files situated one level above the intended output directory.
A Server-Side Request Forgery (SSRF) vulnerability exists in FasterXML jackson-databind before versions 2.18.9, 2.21.5, 2.22.1, 3.1.5, and 3.2.1. The flaw occurs during the deserialization of java.net.InetAddress fields, where the library implicitly triggers eager DNS lookups. Unauthenticated remote attackers can exploit this behavior by passing arbitrary hostnames in JSON fields, forcing target servers to make outbound DNS lookup requests.
An insecure deserialization vulnerability exists in FasterXML jackson-databind due to improper validation of URI schemes when resolving java.nio.file.Path properties. When binding untrusted JSON input to a Path field, the deserializer resolves attacker-supplied URIs without restriction. If the scheme is unrecognized by the default filesystem, the application falls back to querying registered SPI FileSystemProvider instances, causing class loading and potential side effects in environments with custom providers.
CVE-2026-68497 is a high-severity CPU Denial of Service (DoS) vulnerability in jackson-databind. It arises because the library bypasses default input constraint checks when parsing stringified XML datatypes, subsequently passing arbitrary-length inputs to JDK constructors with quadratic execution complexity.