CVE-2026-58045
This Vulnerability has been fixed in the Never-Ending Support (NES) version offered by HeroDevs.
Overview
Node.js is a JavaScript runtime built on Chrome’s V8 JavaScript engine. It uses an event-driven, non-blocking I/O model that makes it lightweight and efficient, and it is widely used for web applications and server-side development.
A denial of service vulnerability (CVE-2026-58045) has been identified in Node.js, where a value that reports a spoofed TypedArray byteLength reaches a bounds assertion inside the synchronous node:zlib APIs and crashes the whole process. Repeated exploitation of this condition can result in a denial of service.
The assigning CNA records this issue as CWE-400: Uncontrolled Resource Consumption. The mechanism the advisory and the upstream fix describe is more precisely a reachable assertion (CWE-617), which MITRE defines as a product that contains "an assert() or similar statement that can be triggered by an attacker, which leads to an application exit or other behavior that is more severe than necessary." Both descriptions agree on the impact: an attacker-influenced value ends the process, and a process that can be ended on demand is unavailable.
This issue affects Node.js releases up to and including v22.23.1, v24.18.0 and v26.5.0. Every End-of-Life release line is affected and receives no upstream fix.
Details
Module Info
- Product: Node.js
- Affected packages: node
- Affected versions:
- <=22.23.1
- >=24.0.0 <=24.18.0
- >=26.0.0 <=26.5.0
- GitHub repository: https://github.com/nodejs/node
- Published packages: https://nodejs.org/en/download
- Package manager: Not applicable. Node.js ships as official binaries and source tarballs from nodejs.org.
- Fixed in: Node.js NES v12.22.20, v14.21.13, v16.20.14, v18.20.19 and v20.20.4. The v14, v16, v18 and v20 releases shipped August 3, 2026; v12.22.20 shipped August 11, 2026.
Vulnerability Info
This Medium-severity vulnerability is found in the Node.js zlib binding (src/node_zlib.cc) and is reachable through the synchronous node:zlib APIs in all affected release lines.
The synchronous compression functions in node:zlib accept a Buffer, TypedArray, DataView, ArrayBuffer or string as their input. The JavaScript layer reads the object’s byte offset and byte length, then passes a pointer together with those two numbers down to the native compression stream, which uses them to locate the bytes it is allowed to read and write.
Because the offset and length come from properties on the object that was handed in, an object whose byteLength and length getters report more memory than actually backs it will produce values that fall outside the real allocation. The native binding did detect that, but it detected it with a CHECK macro, and a failed CHECK aborts the process rather than raising a JavaScript error:
// src/node_zlib.cc, before the fix
CHECK(Buffer::IsWithinBounds(in_off, in_len, Buffer::Length(in_buf)));
...
CHECK(Buffer::IsWithinBounds(out_off, out_len, Buffer::Length(out_buf)));
The upstream fix (commit 0d07248) replaces both assertions with a thrown error, so an out-of-bounds buffer becomes a catchable RangeError with code ERR_OUT_OF_RANGE instead of a process abort:
if (!Buffer::IsWithinBounds(in_off, in_len, Buffer::Length(in_buf))) {
return THROW_ERR_OUT_OF_RANGE(env, "input buffer is out of bounds");
}
The CVSS vector scores the attack vector as local (AV:L), because the attacker needs a crafted value to reach a synchronous zlib call inside the process rather than reaching it across the network. Realistic paths are indirect: a dependency, a plugin, or a deserialized structure that the application forwards to a compression call without first normalizing it to a real Buffer. No privileges and no user interaction are required once such a value can be supplied, and the only impact is availability (C:N/I:N/A:H).
The upstream fix’s own test exercises eleven synchronous functions against a spoofed length: deflateSync, gzipSync, deflateRawSync, unzipSync, inflateSync, gunzipSync, inflateRawSync, brotliCompressSync, brotliDecompressSync, zstdCompressSync and zstdDecompressSync. The bounds check sits in the compression-stream write path shared by all of them, so in older release lines that predate the zstd and Brotli APIs the same path is reached through the deflate, gzip and inflate functions.
Note: The Node.js advisory scopes this issue to the synchronous node:zlib APIs. The fix also adds the same bounds check on the output-buffer offset used by the streaming code path, which the upstream test covers by setting an internal _outOffset past the configured chunk size.
Steps To Reproduce
The steps below follow the test case added by the upstream fix (test/parallel/test-zlib-invalid-input.js).
- Run an affected Node.js version, that is any release up to and including v22.23.1, v24.18.0 or v26.5.0.
- Create a one-byte typed array whose length and byteLength getters report a far larger size than the memory backing it:
const spoofedLength = new Uint8Array(1).fill(0x41);
Object.defineProperty(spoofedLength, 'length', { get: () => 5000 });
Object.defineProperty(spoofedLength, 'byteLength', { get: () => 5000 });
- Pass that object to any synchronous node:zlib function:
const zlib = require('node:zlib');
zlib.deflateSync(spoofedLength);
- On an affected runtime the process aborts on the failed bounds assertion and exits, so no JavaScript error handler runs. On a fixed runtime the same call throws a RangeError with code ERR_OUT_OF_RANGE, which the application can catch.
Mitigation
Node.js release lines v20 and earlier are End-of-Life and will not receive any upstream updates to address this issue. For more information see here. Upstream fixes shipped in the supported lines as v22.23.2, v24.18.1 and v26.5.1 in the Node.js July 29, 2026 security release.
Users of the affected components should apply one of the following mitigations:
- Upgrade to a supported Node.js release that carries the fix (v22.23.2, v24.18.1 or v26.5.1 or later).
- Migrate affected applications away from End-of-Life Node.js release lines.
- Leverage a commercial support partner like HeroDevs for post-EOL security support.
Credits
- byvini (reporter)
- RafaelGSS (remediation developer)