Jul 21, 2026·6 min read·18 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 path traversal vulnerability (CWE-22) in Contao CMS allows unauthenticated remote attackers to bypass directory boundary restrictions in ImagesController and access files within the project directory.
Contao Open Source CMS versions 4.0.0 through 5.3.49 and 5.4.0-RC1 through 5.7.11 contain a Cross-Site Request Forgery (CSRF) vulnerability in backend parameter handling. The `RequestTokenListener` component validates anti-CSRF tokens solely for HTTP POST requests, while GET-based declarative guards run only when an `act` parameter is present in the query string. Consequently, custom backend actions dispatched via alternative parameters such as `key=` can execute without CSRF token verification when triggered by an authenticated user.
Contao CMS versions 4.1.0 through 5.3.49 and 5.4.0-RC1 through 5.7.11 fail to validate form submission tokens and enforce rate limiting when processing activation email resend requests via HTTP POST, enabling resource exhaustion and account state enumeration.
An information disclosure vulnerability in Contao CMS allows unauthenticated site visitors to view protected page titles, URLs, and text excerpts through search queries when protected page indexing is disabled after previously being enabled.
In Vikunja prior to version 2.6.0, relation creation via the CalDAV endpoint fails to invoke the TaskRelation.CanCreate authorization check. This missing access control allows an authenticated user to establish unauthorized relationships and perform write operations against any task, provided its unique identifier (UID) is known.
A cross-project information disclosure vulnerability in Vikunja allows authenticated users with read access to one project to view private task details from unauthorized projects via subtask expansion parameters.