Jul 21, 2026·6 min read·7 visits
Unbounded memory and cookie header limits in Guzzle allow malicious web servers to poison client cookie jars, causing subsequent outgoing requests to be rejected with HTTP 431/400 errors, leading to a denial of service.
An unbounded resource allocation vulnerability exists in Guzzle's cookie parsing and storage engine. Prior to version 7.15.1, Guzzle did not restrict the number or size of cookies stored within the client-side CookieJar. This lack of boundary control allows a malicious server or an intermediary proxy to poison the cookie storage with oversized or excessive Set-Cookie headers. When the client subsequently targets sibling domains or legitimate services using the same cookie jar, it transmits exceptionally large Cookie headers, triggering upstream protocol violations and resulting in Denial of Service (HTTP 431 / HTTP 400 rejection).
The vulnerability exists in guzzlehttp/guzzle, a widely used PHP HTTP client. Guzzle provides cookie management via implementations of CookieJarInterface, allowing clients to preserve and send session cookies across multiple HTTP requests. This application-level cookie engine processes cookie storage internally, bypassing the native cookie handling of underlying transport engines such as libcurl.
Prior to version 7.15.1, Guzzle did not restrict the number or size of cookies stored within the client-side jar. It failed to enforce boundaries on the size of individual Set-Cookie headers or the total count of cookie headers processed from a single HTTP response. This design exposes the client application to potential denial-of-service vectors when communicating with untrusted or compromised servers.
An attacker controlling an upstream HTTP server can exploit this mechanism to inject thousands of large cookie parameters into the client cookie jar. When the client subsequently contacts downstream or sibling APIs using the same cookie jar, it issues oversized HTTP requests. These requests trigger immediate denial of service errors due to protocol restrictions on destination servers.
The underlying vulnerability stems from allocation of resources without limits or throttling (CWE-770) and improper control of sequential memory allocation (CWE-1325). The Guzzle client's CookieJar class parses and persists headers dynamically inside an internal PHP array. The storage loop continues processing items sequentially without enforcing maximum limits on string length or total element counts.
When Guzzle receives a response containing multiple Set-Cookie headers, the CookieJar::extractCookies method extracts each field and inserts it into storage. Because there are no limits on the number of fields or the length of each field, an attacker can transmit multiple megabytes of arbitrary cookie data. The client parses these entries and expands its internal storage, consuming system memory and CPU cycles during the matching process.
Subsequently, during outgoing request generation, the CookieJar::withCookieHeader method matches all saved cookies against the destination URI and concatenates them into a single Cookie header string. If the storage contains hundreds of records, Guzzle produces an exceptionally large header value. When this request is received by reverse proxies, load balancers, or web application firewalls, the upstream infrastructure rejects the transmission because the request header exceeds maximum size limitations.
To understand the technical changes, we examine the difference between the vulnerable implementation and the patched code in src/Cookie/CookieJar.php. The patch limits both input validation and output assembly.
// In the patched code, the class introduces explicit limits
private const MAX_SET_COOKIE_FIELD_LENGTH = 8190;
private const MAX_SET_COOKIE_FIELDS = 50;
private const MAX_REQUEST_COOKIES = 150;
private const MAX_COOKIE_HEADER_LENGTH = 8190;The extractCookies method was updated to implement boundary checks during the response-parsing loop. If an incoming Set-Cookie string exceeds the length limits, it is skipped entirely, protecting memory allocation.
public function extractCookies(RequestInterface $request, ResponseInterface $response): void
{
if ($cookieHeader = $response->getHeader('Set-Cookie')) {
$accepted = 0;
foreach ($cookieHeader as $cookie) {
// Prevent processing of oversized cookie values
if (\strlen($cookie) > self::MAX_SET_COOKIE_FIELD_LENGTH) {
continue;
}
$sc = SetCookie::fromString($cookie);
// ... [Domain parsing logic] ...
// Stop accepting further cookies once the cap is reached
if ($this->setCookie($sc) && ++$accepted === self::MAX_SET_COOKIE_FIELDS) {
break;
}
}
}
}Similarly, outgoing header generation in withCookieHeader now prevents the construction of oversized Cookie header values. The loop terminates before it exceeds length boundaries.
foreach ($this->cookies as $cookie) {
if ($cookie->matchesPath($path) && $cookie->matchesDomain($host)) {
$name = (string) $cookie->getName();
$value = (string) $cookie->getValue();
$separatorLength = $values === [] ? 0 : 2;
$valueLength = \strlen($name) + 1 + \strlen($value);
// Abort header construction if next entry pushes it over 8,190 bytes
if ($headerLength + $separatorLength + $valueLength > self::MAX_COOKIE_HEADER_LENGTH) {
break;
}
$values[] = $name.'='.$value;
$headerLength += $separatorLength + $valueLength;
if (\count($values) === self::MAX_REQUEST_COOKIES) {
break;
}
}
}Exploitation of GHSA-f283-ghqc-fg79 relies on a client-side execution path communicating with a malicious or compromised web service. The attack requires no authentication or special privileges on the client application. The vulnerability is triggered as soon as the Guzzle client attempts to process a response from the adversarial endpoint.
The attacker structures an HTTP response containing dozens of Set-Cookie headers, each populated with random or large alphanumeric strings. Upon receiving this response, the vulnerable Guzzle client updates its local CookieJar storage, adding every entry without validation. The server payload effectively poisons the local cookie state.
When the client application subsequently issues a request using the same CookieJar instance to a legitimate target server, Guzzle automatically compiles the stored values. It generates an outgoing request carrying a multi-kilobyte Cookie header. When the legitimate server or intermediary proxy parses this request, it rejects the traffic, returning an HTTP 431 Request Header Fields Too Large or HTTP 400 Bad Request response, successfully causing a Denial of Service.
The impact of this vulnerability is primarily classified as application-level Denial of Service (DoS) through resource exhaustion and client disruption. While it does not facilitate arbitrary code execution or direct data leakage, it allows external entities to persistently block a client application's ability to communicate with legitimate remote services.
In microservice architectures or webhook integration handlers, a single poisoned shared cookie jar can cause cascading failures. Sibling subdomain poisoning represents a significant secondary risk, where an attacker-controlled subdomain (e.g., attacker.example.com) can infect shared cookie context used to access sensitive subdomains (e.g., secure.example.com). This behavior bypasses domain boundary expectations and corrupts runtime sessions.
The CVSS score is evaluated at 5.3 (Medium), with a vector of CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L. Because exploitation requires no human interaction or elevated privileges, vulnerability scanners and policy compliance tools flag affected instances prior to version 7.15.1 as non-compliant.
The recommended remediation is upgrading the guzzlehttp/guzzle library to version 7.15.1 or later. The update introduces robust limits that protect the processing pipeline from memory and header exhaustion attacks. System administrators and developers can apply the upgrade directly using the Composer package manager.
For systems where immediate upgrades are unfeasible, disabling cookie jars entirely for connections to untrusted APIs provides effective mitigation. Developers can achieve this by configuring the client with ['cookies' => false] in the request options array. If cookie handling is strictly required, implementing a custom wrapper implementing CookieJarInterface that enforces size and count validation is recommended.
To verify the effectiveness of the remediation, developers can run unit tests that inject oversized headers. The test cases must demonstrate that responses containing more than 50 cookies are truncated and individual cookies larger than 8,190 bytes are safely ignored, preserving client stability and preventing HTTP 431 errors.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L| Product | Affected Versions | Fixed Version |
|---|---|---|
guzzle guzzle | < 7.15.1 | 7.15.1 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-770 |
| Attack Vector | Network |
| CVSS | 5.3 |
| EPSS | N/A |
| Impact | Denial of Service (DoS) |
| Exploit Status | Proof of Concept |
| KEV Status | Not Listed |
Allocation of Resources Without Limits or Throttling
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.
CVE-2026-59205 is a high-severity heap-based out-of-bounds write vulnerability affecting Pillow prior to version 12.3.0. The flaw stems from a validation omission in the ImageCmsTransform class where source and destination image modes are not checked against the configurations defined during the creation of the transform. An attacker can exploit this discrepancy to trigger a heap buffer overflow or an out-of-bounds read by supplying an under-allocated target image buffer.
A vulnerability in the 'body-parser' Node.js middleware allows unauthenticated attackers to trigger a Denial of Service. When the 'limit' configuration option is misconfigured with an unparseable type or empty value, size limits fail open. This leads to unrestricted heap memory allocation and process crash via Out of Memory (OOM).