Severity by source
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N
AC:H reflects the non-default manual-serialization prerequisite; S:C reflects downstream proxy/cache poisoning impact on adjacent systems.
Primary rating from Vendor (GitHub_M).
CVSS VectorVendor: GitHub_M
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N
Lifecycle Timeline
3DescriptionCVE.org
guzzlehttp/psr7 is a PSR-7 HTTP message library implementation in PHP. Versions prior to 2.10.2 did not reject ASCII control characters, whitespace, or DEL in first-party URI host components. A vulnerable flow is: First, an application accepts a user-controlled URL. Second, the URL is used to construct a PSR-7 Uri or Request. Third, the host component contains CRLF or another header-unsafe character. Fourth, the host is copied into the PSR-7 Host header when no explicit Host header is provided. Finally, the request is serialized or sent by an HTTP client that does not independently reject the malformed host. In that flow, an attacker can cause the serialized request to contain additional attacker-controlled header lines. For example, a host containing "\r\nX-Injected: yes" can cause the generated Host header to span multiple HTTP header lines. Applications are affected when they use user-controlled URLs for outbound HTTP requests, URL forwarding, proxying, crawling, webhook delivery, or similar request-dispatch flows. In deployments involving HTTP/1.1 connection reuse, proxies, gateways, or load balancers, this malformed request may also contribute to request smuggling or cache poisoning, depending on how downstream components parse the request. The issue is patched in 2.10.2 and later. 1.x is end-of-life and will not receive a patch. As a workaround, validate and reject all untrusted URI strings before constructing PSR-7 Uri or Request instances. Reject input containing ASCII control characters, whitespace, or DEL, including CRLF, tab, space, NUL, or DEL characters. Applications that forward requests should also ensure the final HTTP client or serializer rejects invalid URI and header data before writing requests to the network.
AnalysisAI
CRLF injection in guzzlehttp/psr7 versions prior to 2.10.2 allows remote unauthenticated attackers to inject arbitrary HTTP headers into outbound requests by embedding carriage-return/line-feed sequences in a user-controlled URI host component. When a PSR-7 request is manually serialized into a raw HTTP/1.x message - for example via Message::toString() - the unvalidated host is copied verbatim into the Host header, enabling an attacker-supplied host like '"\r\nX-Injected: yes"' to append controlled headers to the serialized request. In deployments behind proxies, gateways, or load balancers with HTTP/1.1 connection reuse, this header injection can cascade into HTTP request smuggling or cache poisoning. No public exploit code has been identified at time of analysis, and exploitation through the standard Guzzle HTTP client API is explicitly not affected.
Technical ContextAI
guzzlehttp/psr7 is a PHP implementation of the PSR-7 HTTP message interfaces (RequestInterface, UriInterface, etc.), widely used as a foundational dependency in PHP ecosystems - including as a core component of the Guzzle HTTP client. The CPE cpe:2.3:a:guzzle:psr7:*:*:*:*:*:*:*:* covers all versions prior to the fix. The root cause is CWE-20 (Improper Input Validation): the library failed to reject ASCII control characters (0x00-0x1F), whitespace, DEL (0x7F), and specifically CRLF (0x0D 0x0A) within the host component of a constructed Uri or Request object. HTTP/1.x header framing uses CRLF as the line delimiter, so an injected CRLF in the Host field causes parsers to treat the trailing attacker-supplied bytes as a new, distinct header line. This is a classic HTTP response/request splitting primitive (sometimes tagged 'Code Injection' in this advisory's tags). The vulnerability manifests only during raw HTTP/1.x message serialization - the standard GuzzleHttp\Psr7\Message::toString() path - not during in-memory object manipulation or when using Guzzle's standard transport stack, which performs its own header validation.
RemediationAI
The primary fix is to upgrade guzzlehttp/psr7 to version 2.10.2 or later via Composer: run 'composer require guzzlehttp/psr7:^2.10.2'. The patch is confirmed released and documented in the vendor advisory at https://github.com/guzzle/psr7/security/advisories/GHSA-hq7v-mx3g-29hw. Installations on the 1.x branch will not receive a patch - operators on 1.x must migrate to 2.x or apply compensating controls. If an immediate upgrade is not feasible, the vendor-recommended workaround is to validate and reject all untrusted URI strings before constructing PSR-7 Uri or Request instances, using: preg_match('/[\x00-\x20\x7F]/', $untrustedUrl) and throwing an exception on match. This catches CRLF, tab, space, NUL, and DEL characters. Applications that manually serialize PSR-7 requests or forward raw HTTP messages should additionally ensure the final HTTP client or serializer rejects invalid URI and header data before writing to the network. The input-validation workaround adds a rejection step at the application boundary; its trade-off is that it may refuse some edge-case URLs that are technically valid under RFC 3986 but are unlikely to appear in legitimate production traffic.
Host confusion in guzzlehttp/psr7 (all versions prior to 2.10.2) allows unauthenticated network attackers to supply a ma
Host validation bypass in guzzlehttp/psr7 before 2.12.3 enables URI authority confusion attacks against PHP applications
Same weakness CWE-20 – Improper Input Validation
View allSame technique Code Injection
View allShare
External POC / Exploit Code
Leaving vuln.today
EUVD-2026-36240
GHSA-hq7v-mx3g-29hw