CVE-2026-48930
Patch Available.
This Vulnerability has been fixed in the Never-Ending Support (NES) version offered by HeroDevs.
Overview
Node.js is an asynchronous, event-driven JavaScript runtime designed for building scalable network applications. Its dns and net modules, which the http, https and tls modules build on, take hostnames as JavaScript strings and hand them to native resolver bindings written in C++. Those bindings pass the name to the system resolver as a C string, which ends at the first NUL byte.
A hostname confusion vulnerability (CVE-2026-48930) has been identified in Node.js's hostname handling. A hostname is supposed to identify exactly one destination, so the name an application checks is the name it connects to. However, Node.js accepted hostnames containing an embedded NUL byte. JavaScript code saw the whole string, but the resolver binding saw only the part before the NUL, so a name such as one that appears to end in a trusted domain could silently resolve to a different host. Node.js calls this silent authority rebinding: an application can believe it is connecting to one host while actually reaching another.
This behaviour maps to CWE-284 (Improper Access Control), the weakness assigned in the CVE record, where a product does not correctly restrict access to a resource from an unauthorized actor. In Node.js, the controls at risk are the application's own hostname allowlists and authority checks, which inspect the full string while the connection goes to the truncated one. Defeating those checks can expose internal services or send credentials and data to an attacker's host.
Exploitation requires an application that takes a hostname, or a URL whose host it extracts, from untrusted input, checks it in JavaScript, and then passes it to dns.lookup(), dns.promises.lookup() or net.connect() (directly or through http, https or tls). The attacker supplies a name containing a NUL byte so that the checked string and the resolved prefix differ. Applications that only connect to fixed or already-validated hosts are not exposed. The Node.js project describes the issue as affecting its supported 22.x, 24.x and 26.x lines. Node.js has never rejected NUL bytes in these hostnames before this fix, so all earlier release lines are affected as well.
Details
Module Info
- Product: Node.js
- Affected packages: node (built-in dns and net modules; lib/dns.js, lib/internal/dns/promises.js, lib/net.js)
- Affected versions: <=21.7.3 >=22.0.0 <22.23.0 >=23.0.0 <=23.11.1 >=24.0.0 <24.17.0 >=25.0.0 <=25.9.0 >=26.0.0 <26.3.1
- GitHub repository: https://github.com/nodejs/node
- Published packages: https://nodejs.org/en/download
- Package manager: Not applicable; Node.js is distributed as runtime builds from nodejs.org rather than as a published npm package
- Fixed in: Node.js 22.23.0, 24.17.0, and 26.3.1 (upstream fixes, released June 18, 2026); Node.js NES v12.22.19, v14.21.12, v16.20.13, v18.20.18, v20.20.3, v20.20.10, and v22.22.10 (all shipped June 25, 2026), covering the 12.x through 20.x lines that never received an upstream fix before reaching End-of-Life; v20.20.10 and v22.22.10 are custom builds
Vulnerability Info
This Critical-severity vulnerability is found in the hostname validation of dns.lookup(), dns.promises.lookup() and net.Socket.prototype.connect() in Node.js. NVD assigns a CVSS v3.1 score of 9.8; the HackerOne CNA scores it 5.6 (CVSS v3.0) and the Node.js project rates it Medium.
Before resolving a name, these functions are supposed to make sure the string they pass to the native resolver is the same name the caller supplied. In the vulnerable implementation, they only checked that the hostname was a string. A value containing \u0000 was passed through, and the C++ resolver binding read it only up to the NUL, so resolution and connection used a shorter, different name than the one the application had validated. The fix adds a validateStringWithoutNullBytes() check, which throws ERR_INVALID_ARG_VALUE for any hostname containing a NUL byte, to dns.lookup(), dns.promises.lookup() and the host option of net connections. It shipped as commit c551a51d0c on 22.x, 138c70294b on 24.x and bd1214ab01 on 26.x, through nodejs-private pull request #868.
An attacker would need to get a hostname with an embedded NUL byte into an application that validates the full string before connecting. One example is a webhook or proxy feature with a domain allowlist.
Note: Because the NUL byte must reach the resolver intact, applications that only connect to hostnames parsed and normalized by a URL parser that rejects or percent-encodes NUL bytes may not be reachable. This depends on how each application builds the hostname.
Mitigation
Node.js 22.x, 24.x and 26.x are supported and are fixed in 22.23.0, 24.17.0 and 26.3.1 and later. Every other release line is past its support window and never received an upstream fix. Node.js 12.x reached End-of-Life on April 30, 2022; Node.js 14.x on April 30, 2023; Node.js 16.x on September 11, 2023; Node.js 18.x on April 30, 2025; Node.js 20.x on April 30, 2026; Node.js 23.x on June 1, 2025; and Node.js 25.x on June 1, 2026. For more information see here.
Users of the affected components should apply one of the following mitigations:
- Upgrade to Node.js 22.23.0, 24.17.0 or 26.3.1 or later on those lines, all of which include this fix.
- Migrate affected applications away from the End-of-Life Node.js release lines.
- Leverage a commercial support partner like HeroDevs for post-EOL security support, through Node.js NES.
Credits
- tmeletlidis (reporter)
- Matteo Collina (remediation developer)