{"id":"GHSA-g446-98w2-8p5w","summary":"Guzzle: Cookie Disclosure and Injection via IP-Address Domains","details":"### Impact\n\n`CookieJar` does not restrict a cookie scoped to an IP address to the exact host that set it. When a stored cookie's `Domain` attribute is an IPv4 literal (`Domain=192.168.0.1`), a bracketed IPv6 literal (`Domain=[::1]`), or a bare numeric value that denotes an IPv4 address (`Domain=1`, which is `0.0.0.1`), `SetCookie::matchesDomain()` applies ordinary subdomain (suffix) matching to it instead of requiring an exact host. The IP-address check inside `matchesDomain()` is applied only to the request host and never to the cookie's own domain, and response cookies that carry an explicit `Domain` attribute are stored as suffix-matchable. As a result Guzzle sends such a cookie to any host whose name ends in that value as a trailing label, for example sending a `Domain=192.168.0.1` cookie to `evil.192.168.0.1`, or a `Domain=1` cookie to `evil.1`. The same flaw lets a look-alike host store a cookie that Guzzle then sends to the bare IP address. Depending on how the receiving service interprets the cookie, the impact is cross-host cookie disclosure, cookie injection, or session fixation.\n\nYou are affected if your application uses Guzzle's cookie support, for example `new Client(['cookies' =\u003e true])` or an explicit `CookieJar`, reuses one cookie jar across more than one host or trust boundary, and that jar can hold a cookie scoped to an IP-address or bare-numeric host. To actually leak a cookie the application must also resolve and connect to a look-alike host whose name ends in the IP-address label, such as `evil.192.168.0.1`. Such names are not publicly registrable, so in practice an attacker needs some influence over name resolution, which is realistic on private, split-horizon, container, or development networks. You are not affected if you do not use Guzzle's cookie support, if you use a separate cookie jar per host or trust boundary, or if your jars never hold cookies scoped to IP-address or bare-numeric hosts. This issue is independent of public suffix list validation. Per RFC 6265, an IP-address cookie domain must match only the exact host that set it and must never match a subdomain.\n\n### Patches\n\nThe issue is patched in `7.12.3` and later. Starting in that release, Guzzle matches an IPv4 literal, a bracketed IPv6 literal, or a bare-numeric cookie `Domain` only against the exact request host, and no longer applies subdomain suffix matching to them.\n\n### Workarounds\n\nIf you cannot upgrade immediately, do not reuse one `CookieJar` instance across untrusted and trusted origins. Use a separate cookie jar per host or trust boundary, or disable cookie handling for requests to untrusted hosts, and avoid scoping cookies to IP-address or bare-numeric hosts. In particular, avoid `new Client(['cookies' =\u003e true])` for any client that may contact unrelated hosts at different trust levels, because that option creates a single shared jar for the whole client.\n\n### References\n\n* https://datatracker.ietf.org/doc/html/rfc6265#section-5.1.3\n* https://datatracker.ietf.org/doc/html/rfc6265#section-5.3\n* https://url.spec.whatwg.org/#concept-ipv4-parser","aliases":["CVE-2026-59883"],"modified":"2026-07-20T22:15:20.538628246Z","published":"2026-07-20T22:00:09Z","database_specific":{"cwe_ids":["CWE-200","CWE-346","CWE-384"],"severity":"MODERATE","github_reviewed":true,"github_reviewed_at":"2026-07-20T22:00:09Z","nvd_published_at":"2026-07-08T17:17:26Z"},"references":[{"type":"WEB","url":"https://github.com/guzzle/guzzle/security/advisories/GHSA-g446-98w2-8p5w"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-59883"},{"type":"WEB","url":"https://github.com/guzzle/guzzle/pull/3694"},{"type":"WEB","url":"https://github.com/guzzle/guzzle/commit/b9944c161b12d9ee9c9334cfc5b9659ecd7451f8"},{"type":"PACKAGE","url":"https://github.com/guzzle/guzzle"},{"type":"WEB","url":"https://github.com/guzzle/guzzle/releases/tag/7.12.3"}],"affected":[{"package":{"name":"guzzlehttp/guzzle","ecosystem":"Packagist","purl":"pkg:composer/guzzlehttp/guzzle"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"7.12.3"}]}],"versions":["4.0.0","4.0.0-rc.1","4.0.0-rc.2","4.0.1","4.0.2","4.1.0","4.1.1","4.1.2","4.1.3","4.1.4","4.1.5","4.1.6","4.1.7","4.1.8","4.2.0","4.2.1","4.2.2","4.2.3","4.2.4","5.0.0","5.0.1","5.0.2","5.0.3","5.1.0","5.2.0","5.3.0","5.3.1","5.3.2","5.3.3","5.3.4","6.0.0","6.0.1","6.0.2","6.1.0","6.1.1","6.2.0","6.2.1","6.2.2","6.2.3","6.3.0","6.3.1","6.3.2","6.3.3","6.4.0","6.4.1","6.5.0","6.5.1","6.5.2","6.5.3","6.5.4","6.5.5","6.5.6","6.5.7","6.5.8","7.0.0","7.0.0-beta.1","7.0.0-beta.2","7.0.0-rc.1","7.0.1","7.1.0","7.1.1","7.10.0","7.10.1","7.10.2","7.10.3","7.10.4","7.10.5","7.10.6","7.11.0","7.11.1","7.11.2","7.12.0","7.12.1","7.12.2","7.2.0","7.3.0","7.4.0","7.4.1","7.4.2","7.4.3","7.4.4","7.4.5","7.5.0","7.5.1","7.5.2","7.5.3","7.6.0","7.6.1","7.7.0","7.7.1","7.8.0","7.8.1","7.8.2","7.9.0","7.9.1","7.9.2","7.9.3","v1.0.3","v1.0.4","v2.0.0","v2.0.1","v2.0.2","v2.0.3","v2.0.4","v2.0.5","v2.1.0","v2.1.1","v2.1.2","v2.1.3","v2.1.4","v2.2.0","v2.2.1","v2.2.2","v2.2.3","v2.2.4","v2.3.2","v2.4.0","v2.4.1","v2.5.0","v2.6.0","v2.6.1","v2.6.2","v2.6.3","v2.6.4","v2.6.5","v2.6.6","v2.7.0","v2.7.1","v2.7.2","v2.8.0","v2.8.1","v2.8.2","v2.8.3","v2.8.4","v2.8.5","v2.8.6","v2.8.7","v2.8.8","v3.0.0","v3.0.1","v3.0.2","v3.0.3","v3.0.4","v3.0.5","v3.0.6","v3.0.7","v3.1.0","v3.1.1","v3.1.2","v3.2.0","v3.3.0","v3.3.1","v3.4.0","v3.4.1","v3.4.2","v3.4.3","v3.5.0","v3.6.0","v3.7.0","v3.7.1","v3.7.2","v3.7.3","v3.7.4","v3.8.0","v3.8.1"],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/07/GHSA-g446-98w2-8p5w/GHSA-g446-98w2-8p5w.json"}}],"schema_version":"1.9.0","severity":[{"type":"CVSS_V3","score":"CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:L/I:L/A:N"}]}