CVE-2026-59882: guzzlehttp/psr7 Host Confusion Vulnerability
MODERATECVE-2026-59882 is a MODERATE (CVSS 4.2) host confusion vulnerability (CWE-436: Interpretation Conflict) affecting guzzlehttp/psr7 libraries in the Packagist ecosystem. The issue involves host confusion via weak uri host validation. Remediation is available by upgrading affected packages to version 2.12.3.
CVE-2026-59882 at a Glance
Security Impact
CVSS: 4.2
The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:N).
How to Fix CVE-2026-59882
To remediate this vulnerability, upgrade all affected guzzlehttp/psr7 dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.
Upgrade guzzlehttp/psr7 to 2.12.3
Run the following command in your project directory to verify that all resolved dependencies use the patched release:
inspect dependencies for guzzlehttp/psr7
How to Check if You Are Affected
To determine whether your application is affected by CVE-2026-59882, inspect your project dependencies for guzzlehttp/psr7:
inspect dependencies for guzzlehttp/psr7
Analyze the terminal output to locate any version of guzzlehttp/psr7 in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 2.12.3), your application is affected.
Note: Verify declared build manifests and deployed runtime container environments.
Technical Details
Vulnerability Mechanism & Technical Analysis
This vulnerability is classified under CWE-436: Interpretation Conflict, where product a handles inputs or steps differently than product b, which causes a to perform incorrect actions based on its perception of b's state. In guzzlehttp/psr7, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.
Source Advisory Statement
CVE-2026-59882 Affected guzzlehttp/psr7 Versions
1 component(s)| Product / Package | Ecosystem | Affected Versions | Fixed Version |
|---|---|---|---|
|
guzzlehttp/psr7
|
Packagist |
< 2.12.3
|
2.12.3
|
References
Frequently Asked Questions
What is CVE-2026-59882?
Which guzzlehttp/psr7 versions are affected?
What version fixes CVE-2026-59882?
Is guzzlehttp/psr7 affected?
What is the CVSS score of CVE-2026-59882?
What CWE is associated with CVE-2026-59882?
How can I check Packagist dependencies for CVE-2026-59882?
Machine-readable OSV JSON
OSV v1.5 Schema
{
"schema_version" : "1.4.0",
"id" : "GHSA-c2w2-prh8-qm98",
"modified" : "2026-07-21T18:35:25Z",
"published" : "2026-07-21T18:35:25Z",
"aliases" : [ "CVE-2026-59882" ],
"summary" : "guzzlehttp/psr7: Host Confusion via Weak URI Host Validation",
"details" : "### Impact\n\n`guzzlehttp/psr7` did not reject URI host components containing authority delimiters (`/`, `?`, `#`, `@`, or `\\`), an embedded port such as `host:8080`, or IPv6 brackets that do not frame the host (such as `[::1` or `::1]`). `Uri::assertValidHost()` rejected only control characters, so these malformed hosts were accepted both when parsing a URI string — including through `new Uri()`, an absolute-form request target passed to `Message::parseRequest()`, and the synthetic `SERVER_NAME` or `SERVER_ADDR` fallback used by `ServerRequest::fromGlobals()` — and when setting a host with `Uri::withHost()`. Because the stored host was not validated, `Uri::getHost()` could return a value that does not agree with the URI's authority or with the host that is actually used on the wire. For example, `Uri::withHost('good.com@evil.com')` is accepted, and `new Uri('http://[gggg::1]/')` produces a `getHost()` of `'[gggg:'` while `getAuthority()` returns `'[gggg::1'`.\n\nYou are affected if your application builds a `Uri` or calls `Uri::withHost()` with host data that is wholly or partly attacker-controlled and then relies on `Uri::getHost()` for a security or routing decision, such as host allowlisting or denylisting, an SSRF guard, cookie scoping, or proxy-bypass selection. You are also affected if you parse, forward, proxy, or re-serialize URIs that come from untrusted raw HTTP messages or from synthetic `$_SERVER` values. Because `getHost()` can then disagree with the real connection target, the concrete impact depends on how your application and any downstream HTTP/1.x component use the URI, and may include host-based access-control bypass, server-side request forgery, routing to an unintended host, or `Host` header confusion. You are not affected if every host you place into a `Uri` is already trusted and well formed.\n\nApplications using `guzzlehttp/guzzle` are affected in the same way through Guzzle's use of PSR-7. Guzzle derives the request `Host` header from the request URI, and its cookie matching and `no_proxy` proxy-bypass matching both read `Uri::getHost()`. An application that builds a Guzzle request URI from attacker-controlled host input can therefore have its `Host` header, cookie scope, or proxy-bypass decision computed against a host that differs from the one Guzzle connects to. This is not the normal request-sending path, and an application that passes only trusted, well-formed URIs to Guzzle and never builds a request URI from attacker-controlled host input is not affected through Guzzle's standard client APIs.\n\n### Patches\n\nThe issue is patched in `2.12.3` and later. Starting in that release, `guzzlehttp/psr7` rejects URI host components that contain authority delimiters, an embedded port, or IPv6 brackets that do not frame the host, both when parsing a URI and via `Uri::withHost()`, so `Uri::getHost()` agrees with the URI authority. A framed bracketed literal whose contents are not a valid IPv6 address is preserved rather than rejected, so `getHost()` still agrees with the authority.\n\n### Workarounds\n\nIf you cannot upgrade immediately, validate and normalize host values before you build or modify a `Uri` from untrusted input, and do not treat `Uri::getHost()` as a trust boundary for a host you have not independently checked. Before passing a host to `Uri`, reject any value that contains `/`, `?`, `#`, `@`, or `\\`, that contains a colon outside a bracketed IPv6 literal, or that has unbalanced brackets. Applications that parse, forward, replay, or re-serialize raw HTTP messages, or that run with attacker-controlled `$_SERVER` values, should validate the host before calling `Message::parseRequest()` or `ServerRequest::fromGlobals()`, and should avoid reparsing untrusted input.\n\n### References\n\n* https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2\n* https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.3\n* https://datatracker.ietf.org/doc/html/rfc6265#section-5.1.3",
"severity" : [ {
"type" : "CVSS_V3",
"score" : "CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:N"
} ],
"affected" : [ {
"package" : {
"ecosystem" : "Packagist",
"name" : "guzzlehttp/psr7"
},
"ranges" : [ {
"type" : "ECOSYSTEM",
"events" : [ {
"introduced" : "0"
}, {
"fixed" : "2.12.3"
} ]
} ]
} ],
"references" : [ {
"type" : "WEB",
"url" : "https://github.com/guzzle/psr7/security/advisories/GHSA-c2w2-prh8-qm98"
}, {
"type" : "ADVISORY",
"url" : "https://nvd.nist.gov/vuln/detail/CVE-2026-59882"
}, {
"type" : "WEB",
"url" : "https://github.com/guzzle/psr7/pull/811"
}, {
"type" : "WEB",
"url" : "https://github.com/guzzle/psr7/commit/ddd64f17d4cc1f7e5ffe6fd2c989ec7221712580"
}, {
"type" : "PACKAGE",
"url" : "https://github.com/guzzle/psr7"
}, {
"type" : "WEB",
"url" : "https://github.com/guzzle/psr7/releases/tag/2.12.3"
} ],
"database_specific" : {
"cwe_ids" : [ "CWE-20", "CWE-436" ],
"severity" : "MODERATE",
"github_reviewed" : true,
"github_reviewed_at" : "2026-07-21T18:35:25Z",
"nvd_published_at" : "2026-07-08T17:17:26Z"
}
}