Sep 19, 2026·5 min read·74 visits
Uncontrolled memory allocation in adm-zip before 0.6.1 allows unauthenticated remote attackers to trigger a Denial of Service (DoS) via a crafted ZIP archive (decompression bomb) that exhausts Node.js heap memory.
CVE-2026-77301 is a critical uncontrolled resource allocation vulnerability in the popular Node.js library adm-zip (versions prior to 0.6.1). During ZIP decompression of asynchronous entries, the library trusts the uncompressed size metadata declared in the central directory headers. Because Node.js's streaming zlib API completely ignores the maxOutputLength configuration, a crafted ZIP archive (decompression bomb) causes the application to continually allocate resident memory buffers on the heap without limits, causing rapid memory exhaustion and a process-level Out-of-Memory (OOM) crash.
CVE-2026-77301 represents a critical uncontrolled resource allocation vulnerability within the adm-zip Node.js library, affecting all versions prior to 0.6.1. This library is widely integrated across Node.js applications to facilitate archive construction, parsing, and extraction operations. When processing untrusted archives, applications rely heavily on parser-level constraints to prevent resource exhaustion attacks.
The vulnerability is classified under CWE-789 (Memory Allocation with Excessive Size Value) and CWE-770 (Allocation of Resources Without Limits or Throttling). It specifically affects the asynchronous extraction path triggered via getDataAsync(). An attacker can leverage this weakness to submit highly compressed payload streams, inducing rapid exhaustion of the V8 heap and a complete application crash.
The attack vector is network-based and requires no authentication or user interaction. Any exposed API endpoint that accepts file uploads and uses vulnerable versions of adm-zip to extract the payload is fully susceptible to this Denial of Service vector.
The root cause of the vulnerability lies in the interaction between adm-zip and Node.js's native zlib streaming implementation. During decompression, the library's getData() function in zipEntry.js extracts the uncompressed size (expectedLength) from the ZIP file's central directory headers. It then initializes a streaming decompression instance via zlib.createInflateRaw.
To bound memory allocation, adm-zip passes an options object containing maxOutputLength: expectedLength to the stream. However, while Node's synchronous, single-pass unzipSync methods respect maxOutputLength, Node's asynchronous streaming zlib API completely ignores this configuration parameter.
Consequently, the stream's data event handler continuously receives decompressed data chunks. These chunks are appended to a local memory array without any verification. Additionally, if the archive entry specifies an expectedLength of 0, the library omits the size limits entirely, leaving even the synchronous fallback execution path unprotected against decompression bombs.
In vulnerable versions of adm-zip (prior to 0.6.1), the logic in methods/inflater.js initialized the stream configuration by verifying that the declared size was non-zero:
// Vulnerable logic in adm-zip < 0.6.1
const option = version >= 15 && expectedLength > 0 ? { maxOutputLength: expectedLength } : {};If the declared size was zero, the option structure remained empty, disabling the memory allocation cap. During stream processing, the library appended incoming data chunks to the memory array blindly:
// Vulnerable streaming collection loop
tmp.on("data", function (data) {
parts.push(data);
total += data.length;
});In version 0.6.1, the maintainers corrected this behavior. The patch guarantees that a floor value of 1 is utilized for any entry declaring zero bytes, ensuring the option is always populated. Crucially, the library now enforces the boundary manually inside the streaming loop:
// Patched logic in adm-zip 0.6.1
const maxOutputLength = expectedLength > 0 ? expectedLength : 1;
const option = version >= 15 ? { maxOutputLength } : {};
// Manual cap verification in user-land JavaScript
tmp.on("data", function (data) {
if (done) return;
total += data.length;
// Stop decompression immediately if the boundary is exceeded
if (total > maxOutputLength) {
return fail(Errors.MAX_OUTPUT_EXCEEDED());
}
parts.push(data);
});This manual check successfully mitigates the limitation of Node's native streaming zlib implementation, destroying the stream and throwing an error if the accumulated size exceeds the declared limits.
Exploiting this vulnerability requires the construction of a customized zip bomb (decompression bomb). An attacker creates a highly compressed stream of redundant data (such as zero-bytes) that compresses to a negligible size (e.g., 10 KB) but expands into multiple gigabytes upon inflation.
Using specialized tooling or manual binary editing, the attacker manipulates the Central Directory headers of the ZIP file. They overwrite the uncompressed size metadata field for the entry, setting it to 0 or to an extremely high, falsified value.
The attacker then uploads the file to the target Node.js endpoint. Once received, the application invokes asynchronous decompression via the vulnerable package:
const AdmZip = require('adm-zip');
const zip = new AdmZip(req.files.upload.data);
zip.getEntries().forEach(entry => {
entry.getDataAsync((data, err) => {
// Application logic
});
});The unconstrained streaming process rapidly consumes heap memory. Within seconds, the V8 engine reaches its internal memory limit, leading to an uncatchable heap Out-of-Memory exception and crashing the entire server process.
The impact of CVE-2026-77301 is a complete and immediate loss of availability for the targeted service. Because Node.js applications typically run on a single-threaded event loop, a process-level crash drops all active client connections and prevents the processing of any new incoming requests.
The CVSS v3.1 base score is 7.5 (High), reflecting the lack of required privileges or user interaction:
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
In containerized cloud environments, orchestration tools such as Kubernetes may attempt to restart the container following the crash. However, if the malicious request is automatically retried, or if the system processes the payload synchronously on startup, the application will enter an infinite crash loop, maintaining a state of persistent Denial of Service.
The only complete and secure remediation path is to upgrade the adm-zip dependency to version 0.6.1 or later. This introduces the manual verification loop to enforce memory limits during decompression streams.
To upgrade the package in your Node.js application, run:
npm install adm-zip@0.6.1If upgrading is not immediately possible, implement server-side mitigations. Restrict maximum file upload sizes at your reverse proxy, API gateway, or Web Application Firewall (WAF) to prevent the delivery of large zip archives. Additionally, configure process managers such as PM2 to monitor memory utilization and limit crash-loop frequencies.
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.6.1 | 0.6.1 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-789 / CWE-770 |
| Attack Vector | Network (AV:N) |
| CVSS v3.1 Score | 7.5 (High) |
| Exploit Status | PoC (Proof of Concept) |
| CISA KEV Status | Not Listed |
| Impact | Complete Denial of Service (DoS) via OOM Crash |
The software allocates memory based on an untrusted, externally-influenced size value without checking if the allocation exceeds safe limits.
CVE-2026-62374 (GHSA-f9j6-8p6x-r9j6) is a verification bypass vulnerability in the OpenWallet Foundation SD JWT JS library (@sd-jwt/core and @sd-jwt/decode versions 0.19.0 and earlier). Due to permissive UTF-8 decoding and the omission of mandatory reference checks during presentation verification, tampered or unreferenced disclosures are silently dropped rather than rejected. This deviates from RFC 9901 §7.1 requirements and allows attackers to execute silent claim-set reduction attacks against relying parties.
An interpretation conflict in Bytebase DBHub (< 0.22.6) allows attackers to bypass read-only SQL query restrictions when connected to MySQL or MariaDB instances. Because DBHub's custom SQL tokenizer treats any '--' sequence as a comment, whereas MySQL and MariaDB require trailing whitespace or a control character, crafted queries containing '--' immediately followed by non-whitespace characters allow stacked destructive SQL statements to execute on connections configured as read-only.
CVE-2026-118777 is a prototype pollution vulnerability (CWE-1321) in the Forge JavaScript cryptography and networking library (distributed on npm as node-forge) prior to version 1.4.1. The flaw resides in the forge.http client subsystem, where incoming HTTP cookie names and paths parsed from Set-Cookie response headers are stored directly into standard JavaScript objects without key validation or property isolation. By returning crafted Set-Cookie headers containing keys such as __proto__ or constructor, a malicious HTTP server can inject arbitrary properties into Object.prototype, attach attributes to the global Object constructor, or delete built-in prototype methods to cause an application-wide denial of service.
CVE-2026-118775 (GHSA-4642-5mcj-2rqw) is an integer overflow and validation flaw in the ASN.1 serialization module of Forge (node-forge) prior to version 1.4.1. The asn1.oidToDer() function fails to validate the range of the first two arcs of an Object Identifier (OID) and truncates the packed initial subidentifier to a single 8-bit integer. Applications that perform policy checks on untrusted OID strings before encoding them into Distinguished Encoding Rules (DER) format can be tricked into emitting DER bytes that correspond to a completely different, restricted OID.
CVE-2026-119194 is an algorithmic complexity vulnerability (CWE-407) in the pyasn1 library for Python, affecting versions 0.3.3 through 0.6.4. The flaw resides in the schemaless decoding routine ConstructedPayloadDecoderBase._decodeComponentsSchemaless used across BER, CER, and DER codecs. By sending an ASN.1 container populated with child components whose tag identifiers are separated by multiples of CPython's integer hash modulus (sys.hash_info.modulus), an unauthenticated attacker can force worst-case hash collisions in an unbounded Python set, degrading decoding performance from O(N) to O(N^2) and causing a Denial of Service (DoS).
CVE-2026-119195 is an algorithmic complexity vulnerability (CWE-407) in the pyasn1 library for Python, affecting all versions prior to 0.6.5. When decoding constructed strings or indefinite-length ANY types across BER, CER, and certain DER code paths, the payload decoders repeatedly concatenate incoming fragments onto an immutable bytes object using the += operator. Because Python bytes objects cannot be resized in-place, each fragment iteration allocates a new buffer and copies all previously accumulated bytes, resulting in quadratic O(N^2) time and memory copy complexity. An unauthenticated remote attacker can supply a highly fragmented ASN.1 stream to exhaust CPU cycles and stall application worker threads.