Jul 20, 2026·7 min read·9 visits
Guzzle HTTP Client before version 7.12.3 incorrectly applies suffix matching to cookie domains scoped to literal IP addresses, allowing sensitive cookies to be leaked to unauthorized look-alike subdomains.
Guzzle HTTP Client prior to version 7.12.3 contains a logical flaw in its CookieJar component. The client fails to properly validate the host types of stored cookie domain attributes before applying standard suffix-matching logic. As a consequence, sensitive session cookies scoped to an IP address (e.g., 192.168.0.1) can be leaked to malicious, look-alike hostnames (e.g., evil.192.168.0.1). This vulnerability permits cross-host cookie disclosure, cookie injection, and session fixation attacks.
Guzzle is a widely adopted, extensible PHP HTTP client utilized to transmit synchronous and asynchronous HTTP requests across modern web applications. Within its architecture, the CookieJar component serves as the central manager for capturing, maintaining, and attaching cookies to outgoing requests in compliance with RFC 6265 specifications.
Under normal operation, the CookieJar automatically processes the Set-Cookie headers returned by remote servers, storing cookies and evaluating their eligibility for subsequent outbound connections. The vulnerability identified as CVE-2026-59883 exposes a logical flaw in how Guzzle handles cookie domain attributes containing literal IP addresses, bracketed IPv6 strings, or bare-numeric representations.
Rather than enforcing strict origin constraints, Guzzle applied generic suffix-matching rules to these domain types, creating a security boundary breakdown. This design flaw permits sensitive session cookies to cross administrative boundaries, exposing clients to unauthorized credential disclosures and request tampering.
The technical root cause of CVE-2026-59883 lies within the SetCookie::matchesDomain method, which is responsible for evaluating whether a stored cookie should be appended to an outbound request targeting a specific host. According to RFC 6265 Section 5.1.3, suffix matching (which allows subdomains to receive cookies bound to parent domains, such as app.example.com receiving cookies set by example.com) must never be applied to literal IP addresses or bare-numeric hosts. This restriction exists because subdomains or look-alike hostnames mapped relative to an IP address do not share a common administrative origin.
Prior to version 7.12.3, Guzzle implemented a validation check that returned false if the destination request domain was identified as a valid IP address. However, it omitted an equivalent check on the stored cookie's domain attribute itself. When Guzzle processed an outbound request to a target host that was not a literal IP but ended in an IP address suffix (such as evil.192.168.0.1), the validation system failed to recognize the security violation.
Because the requested host evil.192.168.0.1 is not a literal IP, the validation \filter_var($domain, \FILTER_VALIDATE_IP) evaluated to false. Guzzle then proceeded to execute its fallback regular expression validation, which verified whether the target host ended with the cookie's domain attribute. Since evil.192.168.0.1 ends with .192.168.0.1, the regex matched successfully, causing the cookie jar to release the sensitive cookie to the unauthorized destination.
To understand the technical progression of the vulnerability, we examine the logical changes introduced in Guzzle commit b9944c161b12d9ee9c9334cfc5b9659ecd7451f8.
Prior to the patch, the matchesDomain method contained the following vulnerable check sequence:
public function matchesDomain(string $domain): bool
{
if ($cookieDomain === $domain) {
return true;
}
if (\filter_var($domain, \FILTER_VALIDATE_IP)) {
return false;
}
return (bool) \preg_match('/\.'.\preg_quote($cookieDomain, '/').'$/', $domain);
}The patch addresses this structural oversight by introducing an explicit helper method, isIpAddressOrNumericHost(), which identifies whether the cookie's domain attribute represents an IP literal, bracketed IPv6 string, or a bare-numeric host. If this check returns true, the domain matching evaluation terminates early, enforcing exact-match-only constraints for such identifiers.
// Patched logic in SetCookie.php
public function matchesDomain(string $domain): bool
{
if ($cookieDomain === $domain) {
return true;
}
// IP literals and numeric hosts are exact-match-only per RFC 6265.
if (self::isIpAddressOrNumericHost($cookieDomain)) {
return false;
}
if (\filter_var($domain, \FILTER_VALIDATE_IP)) {
return false;
}
return (bool) \preg_match('/\.'.\preg_quote($cookieDomain, '/').'$/', $domain);
}The helper method parses the host string by stripping trailing dots, extracting IPv6 brackets, and executing PHP's internal validation systems to detect numeric endpoints:
private static function isIpAddressOrNumericHost(string $host): bool
{
if ($host !== '' && \str_ends_with($host, '.')) {
$host = \substr($host, 0, -1);
}
if (\str_starts_with($host, '[') && \str_ends_with($host, ']')) {
$host = \substr($host, 1, -1);
}
if (\filter_var($host, \FILTER_VALIDATE_IP) !== false) {
return true;
}
$labels = \explode('.', $host);
$last = (string) \end($labels);
return $last !== '' && \ctype_digit($last);
}While this validation closes the standard attack vector, a residual risk exists in specialized environments where hostnames are specified in non-standard representations, such as hexadecimal IP formats (e.g., 0x7f000001 for 127.0.0.1). In such cases, filter_var and ctype_digit will return false, allowing Guzzle to fallback to suffix-matching rules if the underlying operating system resolver successfully maps the hex IP.
Exploiting CVE-2026-59883 requires the attacker to position a look-alike domain in a routing path accessible to the target Guzzle client, or manipulate DNS resolution to map the suffix-matched host. The physical attack relies on a multi-stage execution model involving session establishment, routing manipulation, and subsequent data extraction.
First, the client initiates a request to a legitimate target server addressed via an IP, such as http://192.168.0.1/. The legitimate server sets a cookie containing a session key, defined with Domain=192.168.0.1. The cookie is processed by Guzzle and added to the active CookieJar.
Second, the attacker leverages a Server-Side Request Forgery (SSRF) vulnerability or triggers a client-side redirect directing Guzzle to issue a request to http://evil.192.168.0.1/. Because Guzzle evaluates the outbound target using the flawed suffix matcher, it identifies 192.168.0.1 as a valid suffix for evil.192.168.0.1 and appends the stored session cookie to the request headers.
Third, the attacker's web server receives the HTTP request containing the exfiltrated session key. This allows the attacker to hijack the active session on the legitimate IP server, bypassing authentication controls.
The security impact of CVE-2026-59883 is characterized by the potential compromise of session confidentiality and authentication token integrity. An attacker who successfully exfiltrates session tokens can assume the identity of the client application when communicating with internal or external endpoints. In cloud-native and microservice architectures where services authenticate using IP-bound session cookies, this leak path is particularly dangerous.
Additionally, the vulnerability permits cookie injection and session fixation attacks. An attacker can set a cookie scoped to evil.192.168.0.1 and rely on Guzzle's suffix matcher to apply that cookie when making requests to 192.168.0.1. This allows the attacker to pre-configure a user session, monitoring actions or hijacking transactions executed by the client application.
The CVSS score is established at 4.7, indicating a medium-severity issue. The rating reflects that while the impact on confidentiality and integrity is significant within localized scopes, the overall attack complexity is high because exploitation depends on routing or DNS control, combined with client-initiated connections to anomalous hosts.
The primary remediation path for CVE-2026-59883 is upgrading the guzzlehttp/guzzle dependency to version 7.12.3 or higher. This update introduces the necessary host validation routines to strictly restrict IP-scoped cookies to exact matches.
For environments where immediate dependency updates are not feasible, developers must implement secondary defensive measures. One immediate workaround is to disable the Guzzle CookieJar middleware when making requests to targets identified by raw IP addresses. If cookie persistence is required, a custom PSR-7 request middleware can be written to intercept response headers and strip the Domain attribute from any Set-Cookie fields that specify an IP address prior to ingestion by Guzzle.
Additionally, egress filtering should be applied at the network or host level to block Guzzle from initiating outbound connections to unexpected hostnames that map to internal IP suffixes. Maintaining strict DNS validation and rejecting dynamic hostname lookups with hybrid IP formats can further isolate the threat surface.
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:L/I:L/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
guzzlehttp/guzzle Guzzle | < 7.12.3 | 7.12.3 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-346 (Origin Validation Error) |
| Attack Vector | Network |
| CVSS v3.1 | 4.7 |
| EPSS Score | 0.00115 |
| Impact | Cross-Host Cookie Disclosure / Injection |
| Exploit Status | none |
| CISA KEV Status | Not Listed |
The software does not properly control the interactions between trusted and untrusted domains, or fails to validate the origin of a request or cookie, leading to unauthorized state transitions or information disclosure.
A heap out-of-bounds write vulnerability exists in Pillow prior to version 12.3.0 due to an integer overflow during image expansion calculations. The subsequent patch introduced a division-by-zero regression causing denial of service.
CVE-2026-59198 is a high-severity heap out-of-bounds read vulnerability in Pillow, the Python imaging library, affecting versions from 5.2.0 up to 12.3.0. The vulnerability occurs in the TGA RLE compression path due to a calculation mismatch between the allocated packed 1-bit row buffer and the byte-level pixel stride assumption in the C-level encoder. This mismatch allows an attacker to leak up to approximately 57 KB of adjacent process heap memory directly into generated TGA image files.
A critical signed 32-bit integer overflow vulnerability was identified in Pillow (Python Imaging Library) versions prior to 12.3.0. The vulnerability resides within the native C extension library (libImaging) during coordinate and bounding box calculations in functions like ImagingPaste and ImagingFill2. Exploitation can bypass bounds and clipping safety checks, leading to a controlled heap backward underwrite and application crash.
CVE-2026-59200 is a high-severity uncontrolled resource consumption vulnerability in the Pillow Python Imaging Library. The flaw resides in the PDF stream decoder, allowing remote, unauthenticated attackers to trigger host out-of-memory crashes by submitting malicious PDF decompression bombs.
A denial-of-service (DoS) vulnerability in Pillow (Python Imaging Library) versions 12.0.0 through 12.2.0 allows unauthenticated remote attackers to trigger 100% CPU utilization and hang the processing thread. The issue occurs within the Encapsulated PostScript (EPS) image parser (PIL/EpsImagePlugin.py) due to missing validation on the byte count parsed from %%BeginBinary: comments, allowing negative values to cause an infinite backward stream seek loop. This formatting-level state-looping issue occurs during the initial format sniffing phase inside Image.open() and does not require the system Ghostscript interpreter to be executed or present. It is resolved in version 12.3.0.
A Denial of Service vulnerability exists in the JPEG2000 decoder of Pillow (versions 8.2.0 to 12.2.0) due to memory allocation state accumulation across tiles, leading to rapid process termination.