Aug 4, 2026·6 min read·3 visits
A vulnerability in undici allows attackers to inject CRLF sequences via duck-typed blob bodies, leading to HTTP Request Smuggling and Header Injection.
CVE-2026-15157 details an improper neutralization of CRLF sequences ('CRLF Injection') within undici, a widely used Node.js HTTP/1.1 client. The vulnerability is triggered when processing request bodies that exhibit a duck-typed blob-like interface. When an application accepts untrusted data and assigns it to the .type property of such an object without setting an explicit Content-Type on the request, undici appends the value directly to the outgoing headers array without validating it against control characters. This allows remote attackers to inject carriage return and line feed sequences, culminating in arbitrary header injection, HTTP response splitting, or HTTP request smuggling.
The undici HTTP client library serves as a cornerstone for modern Node.js networking, delivering a high-performance HTTP/1.1 implementation. Applications routinely rely on undici to manage outward-bound communication, utilizing its dispatch pipelines to transmit various request payloads. The attack surface of concern involves outgoing requests that process non-standard or 'duck-typed' blob-like bodies.
Under specific circumstances, undici automates the generation of request headers to simplify operations for developers. If an outgoing request does not contain an explicit 'Content-Type' header, the dispatcher inspects the request body object. If this object mimics the native Blob interface, undici extracts its .type property and injects it directly into the outbound headers stream.
This automatic populating of headers introduces a serious vulnerability when the input is untrusted. Because the dispatcher did not subject this auto-extracted header to validation checks, it became a direct sink for Carriage Return and Line Feed (CRLF) characters. This class of flaw is classified under CWE-93, indicating an Improper Neutralization of CRLF Sequences.
The root cause of CVE-2026-15157 resides in the HTTP/1.1 dispatcher implementation located inside lib/dispatcher/client-h1.js. Specifically, the vulnerability manifests when processing the request payload within the writeH1 function. The dispatcher relies on the helper utility util.isBlobLike(body) to determine whether the incoming body possesses a Blob-like contract.
If the application developer has not defined a 'Content-Type' header, and the body object exhibits a truthy .type property, the vulnerable codebase executes the following instruction: headers.push('content-type', body.type). This step completely bypasses the header validation mechanism that governs other standard headers.
Normally, outgoing headers are validated to ensure they do not contain control characters or carriage returns. By pushing the raw body.type value directly into the serialization array, undici creates an unvalidated pathway. When the application writes this array to the underlying TCP socket, the raw CRLF sequences are interpreted by the receiving end as delimiters, causing the stream to segment prematurely.
A comparison of the vulnerable and patched versions reveals the exact injection point and the introduced validation guards. The fix was applied across the maintained branches in commits such as 33928bc24f742ea8422ed90d17f2e0cc83e4d09d.
@@ -1200,8 +1201,16 @@ function writeH1 (client, request) {
}
body = bodyStream.stream
contentLength = bodyStream.length
- } else if (util.isBlobLike(body) && request.contentType == null && body.type) {
- headers.push('content-type', body.type)
+ } else if (util.isBlobLike(body) && request.contentType == null) {
+ const contentType = body.type
+ if (contentType) {
+ const contentTypeValue = `${contentType}`
+ if (!util.isValidHeaderValue(contentTypeValue)) {
+ util.errorRequest(client, request, new InvalidArgumentError('invalid content-type header'))
+ return false
+ }
+ headers.push('content-type', contentTypeValue)
+ }
}The patch addresses the vulnerability with two primary additions. First, it extracts the contentType property and forces string coercion using template literals: const contentTypeValue = \${contentType}``. This coercion is a defense against Time-of-Check to Time-of-Use (TOCTOU) exploits, where a JavaScript Proxy could return a safe value during validation and a malicious string during serialization.
Second, the coerced string is analyzed using util.isValidHeaderValue(contentTypeValue). This function checks the string against defined specifications, ensuring that no control characters, including \r and \n, are present. If validation fails, undici immediately terminates the request and raises an InvalidArgumentError instead of writing corrupt sequences to the network socket.
Exploiting CVE-2026-15157 requires a specific alignment of application conditions. An attacker must find an application endpoint that accepts input and uses it to construct a custom object resembling a Blob. Furthermore, this object must be passed as a request body to undici, without the developer overriding the Content-Type header.
When these conditions are met, the attacker supplies a payload containing CRLF sequences. For instance, the attacker provides a string such as application/json\r\nInjected-Header: value. When undici serializes the headers, the downstream receiving server processes the raw bytes.
The receiving proxy identifies the first CRLF sequence as the end of the Content-Type header. It then reads the subsequent characters (Injected-Header: value) as an entirely separate header block. Under advanced conditions, the attacker can insert multiple CRLF sequences followed by a full HTTP request body, achieving HTTP Request Smuggling.
The primary risk associated with this CRLF injection is the compromise of message integrity across the delivery path. Because reverse proxies and load balancers rely heavily on explicit header boundaries to route traffic, injecting arbitrary headers allows attackers to manipulate proxy logic.
This manipulation can result in Web Cache Poisoning, where an attacker injects headers that force cache engines to store malicious responses under benign keys. Additionally, attackers can bypass security controls or web application firewalls (WAFs) by smuggling request payloads that are hidden from inspection engines.
This vulnerability has been assigned CVSS v3.1 base score of 4.2 (Medium), with a vector of CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:N. The exploitability is limited by the requirement that applications must use custom, duck-typed blob shapes constructed from user input, as native runtime Blobs naturally sanitize the type property during instantiation.
Remediation requires updating undici to the corrected releases. Organizations should update dependencies to 6.28.0, 7.29.0, or 8.9.0 depending on their active release line. These versions correctly validate the headers during dispatch.
If immediate patching is unfeasible, developers must employ defensive code changes. The most direct workaround is to explicitly define the Content-Type header in the request options passed to undici. This step bypasses the vulnerable automatic header assignment logic entirely.
Additionally, applications that wrap or construct custom file-like objects from user parameters should perform strict verification. Sanitizing metadata properties to strip any carriage return and line feed characters prior to object property assignments provides defense-in-depth protection.
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
undici Node.js | < 6.28.0 | 6.28.0 |
undici Node.js | >= 7.0.0 < 7.29.0 | 7.29.0 |
undici Node.js | >= 8.0.0 < 8.9.0 | 8.9.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-93 |
| Attack Vector | Network |
| CVSS v3.1 | 4.2 (Medium) |
| EPSS Score | 0.00142 |
| Impact | Low Confidentiality, Low Integrity |
| Exploit Status | PoC Available |
| KEV Status | Not Listed |
The product receives input from an upstream component but does not neutralize or incorrectly neutralizes carriage return (CR) and line feed (LF) characters before writing to an output stream interpreted as a protocol structure.
CVE-2026-16729 (GHSA-v3r7-h72x-cjcm) is a medium-severity cookie attribute injection vulnerability in Undici's web-compliant cookie utility module. Due to insufficient validation of domain parameters and raw attributes in the unparsed options array, arbitrary attributes like SameSite, HttpOnly, and Secure can be injected. This allows attackers to bypass CSRF protections, strip security flags, or override intended cookie behaviors when applications pass user-controlled values to these properties.
An interpretation conflict (CWE-436) in the cache interceptor of the undici HTTP client for Node.js causes whitespace-padded Cache-Control directives to be parsed incorrectly, leading to shared cache pollution and the unauthorized disclosure of sensitive, private, or authenticated user information (CWE-524).
A trust-boundary bypass and Server-Side Request Forgery (SSRF) vulnerability exists in the ip-address library versions 10.1.1 through 10.2.0 due to structural input misclassification. The library fails to resolve and normalize transition IP notations, such as IPv4-mapped IPv6 (::ffff:0:0/96) and NAT64 (64:ff9b::/96) addresses, to their embedded IPv4 representations prior to evaluation. Consequently, standard security validation checks (e.g., isLoopback, isLinkLocal, isULA) return false for these addresses. This allows remote attackers to bypass application-level IP address filters, gaining unauthorized access to internal resources, cloud metadata interfaces, and local services on dual-stack hosts or environments utilizing NAT64 gateways.
A critical authentication bypass vulnerability (CVE-2026-18574) in Check Point Security Management and Multi-Domain Security Management (MDS) Servers allows unauthenticated remote attackers to execute arbitrary system commands with administrative privileges. The flaw stems from an alternate path authentication bypass (CWE-288) in the management interface daemons.
An input validation vulnerability in the npm package `ip-address` allows unauthenticated remote attackers to bypass Server-Side Request Forgery (SSRF) protections by appending a `/0` CIDR suffix to IP address strings. This causes the library's classification helper functions to incorrectly identify internal addresses as public, external addresses, while normalization helpers resolve the address back to its internal form during network connection establishment.
An argument injection vulnerability in GitPython allows remote or local attackers to execute arbitrary file reads or arbitrary file overwrites via unsafe command option forwarding. This occurs because the wrapper methods `IndexFile.checkout()` and `TagReference.create()` fail to validate parameters before passing them to system-level git invocations.