{"id":"CVE-2026-59882","aliases":["CLSA-2026-1785554486","CLSA-2026-1786346242","CLSA-2026-1786527009","DEBIAN-CVE-2026-59882","EUVD-2026-42319","GHSA-c2w2-prh8-qm98","UBUNTU-CVE-2026-59882"],"status":"published","title":"guzzlehttp/psr7: Host Confusion via Weak URI Host Validation","description":"guzzlehttp/psr7 is a PSR-7 HTTP message library implementation in PHP. Prior to 2.12.3, Uri::assertValidHost() does not reject URI host components containing authority delimiters, embedded ports, or malformed IPv6 brackets, allowing Uri::getHost() to disagree with the URI authority used for security or routing decisions. This issue is fixed in version 2.12.3.","severity":{"version":"3.1","score":4.2,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:N","level":"medium","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-10","score":0.00317,"percentile":0.24887,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-20","CWE-436"],"published":"2026-07-08T15:50:03Z","modified":"2026-10-28T02:30:36Z","fixes":[{"ecosystem":"Packagist","package":"guzzlehttp/psr7","fixed_in":["2.12.3"],"sources":["ghsa","osv"]},{"ecosystem":"TuxCare:Packagist","package":"guzzlehttp/psr7","fixed_in":["1.9.1-p2+tuxcare"],"sources":["osv"]},{"ecosystem":"Debian:14","package":"php-guzzlehttp-psr7","fixed_in":["2.12.3-1"],"sources":["osv"]}],"affected":[{"source":"ghsa","ecosystem":"Packagist","package":"guzzlehttp/psr7","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.12.3"}]}]},{"source":"osv","ecosystem":"TuxCare:Packagist","package":"guzzlehttp/psr7","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"1.4.2"},{"fixed":"1.4.2-p2+tuxcare"}]}],"versions":["1.4.2","1.4.2-p1+tuxcare"],"bundled":2},{"source":"osv","ecosystem":"TuxCare:Packagist","package":"guzzlehttp/psr7","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"1.9.1"},{"fixed":"1.9.1-p2+tuxcare"}]}],"versions":["1.9.1","1.9.1-p1+tuxcare"]},{"source":"osv","ecosystem":"TuxCare:Packagist","package":"guzzlehttp/psr7","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"1.1.0"},{"fixed":"1.1.0-p1+tuxcare"}]}],"versions":["1.1.0"],"bundled":5},{"source":"osv","ecosystem":"Debian:12","package":"php-guzzlehttp-psr7","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["2.10.3-1","2.10.4-1","2.11.0-1","2.12.0-1","2.12.1-1","2.12.3-1","2.12.4-1","2.12.5-1","2.13.0-1","2.13.1-1","2.4.5-1","2.4.5-1+deb12u1","2.5.0-1","2.6.0-1","2.6.1-1","2.6.2-1","2.6.2-2","2.6.2-3","2.7.0-1","2.7.0-2","2.7.0-3","2.7.1-1","2.8.0-1","2.8.0-2","2.9.0-1","2.9.0-2","3.0.0-1","3.1.0-1","3.2.0-1"]},{"source":"osv","ecosystem":"Debian:13","package":"php-guzzlehttp-psr7","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["2.10.3-1","2.10.4-1","2.11.0-1","2.12.0-1","2.12.1-1","2.12.3-1","2.12.4-1","2.12.5-1","2.13.0-1","2.13.1-1","2.7.1-1","2.7.1-1+deb13u1","2.7.1-1+deb13u2","2.8.0-1","2.8.0-2","2.9.0-1","2.9.0-2","3.0.0-1","3.1.0-1","3.2.0-1"]},{"source":"osv","ecosystem":"Debian:14","package":"php-guzzlehttp-psr7","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.12.3-1"}]}],"versions":["2.10.3-1","2.10.4-1","2.11.0-1","2.12.0-1","2.12.1-1","2.7.1-1","2.8.0-1","2.8.0-2","2.9.0-1","2.9.0-2"]},{"source":"osv","ecosystem":"Packagist","package":"guzzlehttp/psr7","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.12.3"}]}],"versions":["1.0.0","1.1.0","1.2.0","1.2.1","1.2.2","1.2.3","1.3.0","1.3.1","1.4.0","1.4.1","1.4.2","1.5.0","1.5.1","1.5.2","1.6.0","1.6.1","1.7.0","1.8.0","1.8.1","1.8.2","1.8.3","1.8.4","1.8.5","1.9.0","1.9.1","2.0.0","2.0.0-beta1","2.0.0-rc1","2.1.0","2.1.1","2.1.2","2.10.0","2.10.1","2.10.2","2.10.3","2.10.4","2.11.0","2.11.1","2.12.0","2.12.1","2.12.2","2.2.0","2.2.1","2.2.2","2.3.0","2.4.0","2.4.1","2.4.2","2.4.3","2.4.4","2.4.5","2.5.0","2.5.1","2.6.0","2.6.1","2.6.2","2.6.3","2.7.0","2.7.1","2.8.0","2.8.1","2.9.0","2.9.1"]},{"source":"osv","ecosystem":"Ubuntu:16.04:LTS","package":"php-guzzlehttp-psr7","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["1.1.0-1","1.2.0-1","1.2.1-1","1.2.2-1","1.2.2-1build1","1.2.2-1ubuntu1"]},{"source":"osv","ecosystem":"Ubuntu:20.04:LTS","package":"php-guzzlehttp-psr7","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["1.4.2-0.1","1.4.2-0.1+deb10u2build0.20.04.1"]},{"source":"osv","ecosystem":"Ubuntu:Pro:22.04:LTS","package":"php-guzzlehttp-psr7","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["1.7.0-1","1.8.3-1","1.8.3-1ubuntu0.1~esm1"]},{"source":"osv","ecosystem":"Ubuntu:24.04:LTS","package":"php-guzzlehttp-psr7","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["2.6.0-1","2.6.1-1","2.6.2-1"]},{"source":"osv","ecosystem":"Ubuntu:25.10","package":"php-guzzlehttp-psr7","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["2.7.0-3","2.7.1-1"]},{"source":"osv","ecosystem":"Ubuntu:26.04:LTS","package":"php-guzzlehttp-psr7","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["2.7.1-1","2.8.0-1","2.8.0-2"]}],"products":[{"vendor":"guzzle","product":"psr7"},{"vendor":"guzzlephp","product":"psr-7"}],"references":[{"url":"https://github.com/guzzle/psr7/security/advisories/GHSA-c2w2-prh8-qm98","tags":["x_refsource_CONFIRM","Mitigation","Vendor Advisory","advisory","web","report"]},{"url":"https://github.com/guzzle/psr7/pull/811","tags":["x_refsource_MISC","Issue Tracking","Patch","fix","web","report"]},{"url":"https://github.com/guzzle/psr7/commit/ddd64f17d4cc1f7e5ffe6fd2c989ec7221712580","tags":["x_refsource_MISC","Patch","fix","web"]},{"url":"https://github.com/guzzle/psr7/releases/tag/2.12.3","tags":["x_refsource_MISC","Product","Release Notes","web"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-59882","tags":["advisory"]},{"url":"https://github.com/advisories/GHSA-c2w2-prh8-qm98"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/59xxx/CVE-2026-59882.json","tags":["advisory"]},{"url":"https://security-tracker.debian.org/tracker/CVE-2026-59882","tags":["advisory"]},{"url":"https://github.com/guzzle/psr7","tags":["package"]},{"url":"https://ubuntu.com/security/CVE-2026-59882","tags":["report"]},{"url":"https://www.cve.org/CVERecord?id=CVE-2026-59882","tags":["report"]}],"sources":{"cve":[{"id":"CVE-2026-59882","title":"guzzlehttp/psr7: Host Confusion via Weak URI Host Validation","description":"guzzlehttp/psr7 is a PSR-7 HTTP message library implementation in PHP. Prior to 2.12.3, Uri::assertValidHost() does not reject URI host components containing authority delimiters, embedded ports, or malformed IPv6 brackets, allowing Uri::getHost() to disagree with the URI authority used for security or routing decisions. This issue is fixed in version 2.12.3.","status":"published","published":"2026-07-08T15:50:03.077Z","modified":"2026-07-08T17:00:22.945Z","cvss":[{"version":"3.1","score":4.2,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:N","level":"medium","assessor":"cna"}],"cwes":["CWE-436"],"updated_at":"2026-11-02T14:19:58.944663Z"}],"euvd":[{"id":"EUVD-2026-42319","description":"guzzlehttp/psr7 is a PSR-7 HTTP message library implementation in PHP. Prior to 2.12.3, Uri::assertValidHost() does not reject URI host components containing authority delimiters, embedded ports, or malformed IPv6 brackets, allowing Uri::getHost() to disagree with the URI authority used for security or routing decisions. This issue is fixed in version 2.12.3.","status":"published","published":"2026-07-08T15:50:03Z","modified":"2026-07-08T17:00:22Z","cvss":[{"version":"3.1","score":4.2,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:N","level":"medium"}],"updated_at":"2026-11-02T18:20:10.095263Z"}],"ghsa":[{"id":"GHSA-c2w2-prh8-qm98","title":"guzzlehttp/psr7: Host Confusion via Weak URI Host Validation","description":"### 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","status":"published","published":"2026-07-21T18:35:25Z","modified":"2026-07-21T18:35:26Z","cvss":[{"version":"3.1","score":4.2,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:N","level":"medium"}],"cwes":["CWE-20","CWE-436"],"updated_at":"2026-11-02T14:40:50.444681Z"}],"nvd":[{"id":"CVE-2026-59882","description":"guzzlehttp/psr7 is a PSR-7 HTTP message library implementation in PHP. Prior to 2.12.3, Uri::assertValidHost() does not reject URI host components containing authority delimiters, embedded ports, or malformed IPv6 brackets, allowing Uri::getHost() to disagree with the URI authority used for security or routing decisions. This issue is fixed in version 2.12.3.","status":"published","published":"2026-07-08T17:17:26.597Z","modified":"2026-10-25T17:10:00.197Z","cvss":[{"version":"3.1","score":4.2,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:N","level":"medium","assessor":"secondary"},{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N","level":"medium","assessor":"primary"}],"cwes":["CWE-436"],"updated_at":"2026-11-02T14:12:28.040501Z"}],"osv":[{"id":"CVE-2026-59882","title":"guzzlehttp/psr7: Host Confusion via Weak URI Host Validation","description":"guzzlehttp/psr7 is a PSR-7 HTTP message library implementation in PHP. Prior to 2.12.3, Uri::assertValidHost() does not reject URI host components containing authority delimiters, embedded ports, or malformed IPv6 brackets, allowing Uri::getHost() to disagree with the URI authority used for security or routing decisions. This issue is fixed in version 2.12.3.","status":"published","published":"2026-07-08T15:50:03.077Z","modified":"2026-10-28T02:30:36.636481338Z","cvss":[{"version":"3.1","score":4.2,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:N","level":"medium"}],"cwes":["CWE-436"],"updated_at":"2026-11-02T15:45:12.496548Z"},{"id":"DEBIAN-CVE-2026-59882","description":"guzzlehttp/psr7 is a PSR-7 HTTP message library implementation in PHP. Prior to 2.12.3, Uri::assertValidHost() does not reject URI host components containing authority delimiters, embedded ports, or malformed IPv6 brackets, allowing Uri::getHost() to disagree with the URI authority used for security or routing decisions. This issue is fixed in version 2.12.3.","status":"published","published":"2026-07-08T17:17:26.597Z","modified":"2026-10-26T12:01:32.979410614Z","cvss":[{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N","level":"medium"}],"updated_at":"2026-11-02T15:45:57.932517Z"},{"id":"GHSA-c2w2-prh8-qm98","title":"guzzlehttp/psr7: Host Confusion via Weak URI Host Validation","description":"### 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","status":"published","published":"2026-07-21T18:35:25Z","modified":"2026-07-21T18:46:10.53734555Z","cvss":[{"version":"3.1","score":4.2,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:N","level":"medium"}],"cwes":["CWE-20","CWE-436"],"updated_at":"2026-11-02T15:46:44.571161Z"},{"id":"UBUNTU-CVE-2026-59882","description":"guzzlehttp/psr7 is a PSR-7 HTTP message library implementation in PHP. Prior to 2.12.3, Uri::assertValidHost() does not reject URI host components containing authority delimiters, embedded ports, or malformed IPv6 brackets, allowing Uri::getHost() to disagree with the URI authority used for security or routing decisions. This issue is fixed in version 2.12.3.","status":"published","published":"2026-07-08T17:17:00Z","modified":"2026-07-24T15:47:07.009446899Z","cvss":[{"version":"3.1","score":4.2,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:N","level":"medium"},{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N","level":"medium"}],"updated_at":"2026-11-02T16:56:41.911783Z"},{"id":"CLSA-2026-1785554486","title":"TuxCare security update for guzzlehttp/psr7 (2 CVEs)","description":"TuxCare rebuilt guzzlehttp/psr7 to address 2 CVEs. Fixed in 1.4.2-p2+tuxcare.","status":"published","published":"2026-08-04T14:52:51Z","modified":"2026-10-15T09:47:59.554480554Z","updated_at":"2026-11-02T15:43:46.850893Z"},{"id":"CLSA-2026-1786346242","title":"TuxCare security update for guzzlehttp/psr7 (1 CVE)","description":"TuxCare rebuilt guzzlehttp/psr7 to address 1 CVE. Fixed in 1.9.1-p2+tuxcare.","status":"published","published":"2026-08-10T07:17:22Z","modified":"2026-10-15T09:47:59.49532071Z","updated_at":"2026-11-02T15:43:46.850893Z"},{"id":"CLSA-2026-1786527009","title":"TuxCare security update for guzzlehttp/psr7 (5 CVEs)","description":"TuxCare rebuilt guzzlehttp/psr7 to address 5 CVEs. Fixed in 1.1.0-p1+tuxcare.","status":"published","published":"2026-08-12T09:30:09Z","modified":"2026-10-15T09:47:59.529563331Z","updated_at":"2026-11-02T15:43:46.850893Z"}]}}
