Skip to content

🚨 [security] [php] Update guzzlehttp/guzzle 7.9.3 → 7.12.1 (minor)#121

Open
depfu[bot] wants to merge 1 commit into
mainfrom
depfu/update/composer/guzzlehttp/guzzle-7.12.1
Open

🚨 [security] [php] Update guzzlehttp/guzzle 7.9.3 → 7.12.1 (minor)#121
depfu[bot] wants to merge 1 commit into
mainfrom
depfu/update/composer/guzzlehttp/guzzle-7.12.1

Conversation

@depfu

@depfu depfu Bot commented Jun 19, 2026

Copy link
Copy Markdown

🚨 Your current dependencies have known security vulnerabilities 🚨

This dependency update fixes known security vulnerabilities. Please see the details below and assess their impact carefully. We recommend to merge and deploy this as soon as possible!


Here is everything you need to know about this update. Please take a good look at what changed and the test results before merging this pull request.

What changed?

↗️ guzzlehttp/guzzle (indirect, 7.9.3 → 7.12.1) · Repo · Changelog

Security Advisories 🚨

🚨 guzzlehttp/guzzle: Silent HTTPS-Proxy Downgrade to Cleartext

Impact

The built-in cURL handlers (GuzzleHttp\Handler\CurlHandler and GuzzleHttp\Handler\CurlMultiHandler, used by default whenever the PHP cURL extension is available) accept an https:// proxy — a proxy reached over a TLS-encrypted connection — through the proxy request option, client-level proxy defaults, or proxy environment variables such as http_proxy, https_proxy, HTTPS_PROXY, all_proxy, and ALL_PROXY.

When the installed libcurl does not support HTTPS proxies, behavior depends on the libcurl version/build:

  • libcurl older than 7.50.2 silently treats an https:// proxy as a plaintext http:// proxy. The TLS connection to the proxy is never established, and the proxy leg is cleartext with no error or warning.
  • libcurl 7.50.2 through 7.51.x rejects the unsupported proxy scheme at connect time, so no cleartext exposure occurs, but the failure is late and opaque.
  • libcurl 7.52.0 or newer builds without HTTPS-proxy support also fail at connect time rather than downgrading.

The security-relevant case is the silent downgrade on libcurl older than 7.50.2. An application is affected when it sends requests through one of the built-in cURL handlers, configures an https:// proxy expecting the proxy connection itself to be encrypted, and runs with libcurl older than 7.50.2.

In that configuration, traffic expected to be protected by TLS on the hop to the proxy is transmitted in cleartext. Proxy authentication credentials (the Proxy-Authorization header, proxy userinfo in the proxy URL, or CURLOPT_PROXYUSERPWD) are sent without encryption, and the CONNECT target host and port for tunneled HTTPS requests are exposed. For plain HTTP requests, request headers and bodies are also exposed on the proxy leg. End-to-end HTTPS requests tunneled through the proxy remain protected by their inner TLS session; the exposure is limited to the proxy negotiation and proxy credentials.

Applications that do not configure an https:// proxy are not affected. Installations running libcurl 7.52.0 or newer built with HTTPS-proxy support are not affected because HTTPS proxies work as intended. Installations running libcurl 7.50.2 through 7.51.x, or libcurl 7.52.0 or newer built without HTTPS-proxy support, are not exposed to the silent cleartext downgrade, but Guzzle now rejects those unsupported configurations up front as well. The built-in stream handler is not affected; the issue is specific to the cURL handlers' proxy handling. Low-level cURL options under the curl request option, such as CURLOPT_PROXY or CURLOPT_PROXYTYPE, are advanced custom configuration and remain the caller's responsibility.

Patches

The issue is patched in 7.12.1 and later. Starting in that release, the built-in cURL handlers detect whether the installed libcurl supports HTTPS proxies — requiring both libcurl 7.52.0 or newer and the CURL_VERSION_HTTPS_PROXY feature bit — and reject a request configured through Guzzle's first-class proxy handling with an https:// proxy up front by throwing a GuzzleHttp\Exception\RequestException. No request bytes reach the network when the proxy cannot be used securely. Versions before 7.12.1 are affected by the silent downgrade when run against libcurl older than 7.50.2.

Workarounds

If you cannot upgrade immediately, do not configure an https:// proxy on an installation whose libcurl lacks HTTPS-proxy support, and verify the capability in application code before using one. Remember to check proxy environment variables as well as any explicit proxy option:

$curl = \curl_version();
$httpsProxyBit = \defined('CURL_VERSION_HTTPS_PROXY') ? \CURL_VERSION_HTTPS_PROXY : (1 << 21);

if (\version_compare($curl['version'], '7.52.0', '<') || 0 === ($curl['features'] & $httpsProxyBit)) {
throw new <span class="pl-v">RuntimeException('Installed libcurl does not support HTTPS proxies.');
}

Upgrading the system libcurl to 7.52.0 or newer built with HTTPS-proxy support also resolves the underlying unsupported-proxy behavior.

🚨 guzzlehttp/guzzle: Dot-Only Cookie Domains Match All Hosts

Impact

CookieJar incorrectly accepts cookies with a dot-only Domain attribute, such as Domain=., Domain=.., Domain=..., and whitespace-padded variants such as Domain= . . In affected versions, SetCookie::matchesDomain() removes leading dots from the cookie domain, normalizing dot-only values to the empty string; SetCookie::validate() only rejected a strictly empty domain, so these cookies could be stored and the empty normalized domain was treated as matching any request host.

An attacker-controlled origin that an application requests with a shared cookie jar can therefore set a cookie that Guzzle later sends to unrelated hosts using the same jar. This may allow cookie injection or session fixation against downstream services, depending on how those services interpret the injected cookie. Applications are affected when they use Guzzle's cookie support, for example new Client(['cookies' => true]) or an explicit shared CookieJar, and reuse the same jar across attacker-controlled and trusted origins.

Applications that do not use Guzzle's cookie support, or that use separate cookie jars per origin or trust boundary, are not affected. This issue is distinct from public suffix list validation: dot-only domains contain no domain label and should not match unrelated hosts.

Patches

The issue is patched in 7.12.1 and later. Starting in that release, Guzzle rejects dot-only cookie Domain attributes and prevents an empty normalized cookie domain from matching any request host.

Workarounds

If you cannot upgrade immediately, do not reuse the same CookieJar instance across untrusted and trusted origins. Use separate cookie jars per origin or trust boundary, or disable cookie handling for requests to untrusted hosts.

Avoid using new Client(['cookies' => true]) for clients that may contact unrelated hosts with different trust levels, because that option creates one shared jar for the client.

Release Notes

7.12.1

Changed

  • Adjusted guzzlehttp/psr7 version constraint to ^2.12.1

Fixed

  • Reject proxy URLs with a malformed scheme in the cURL handlers instead of letting libcurl mishandle them

Security

7.11.1

Fixed

  • Ignore request-level transport_sharing, matching other unknown request options

7.11.0

Added

  • Added support for providing the proxy request option's no value as a comma-delimited string
  • Added the protocols request option to restrict allowed URI schemes for request transfers
  • Added cert_type and ssl_key_type request options for TLS certificate and private-key file types
  • Added PHP stream handler support for the ssl_key request option
  • Added transport sharing via the transport_sharing client and cURL handler options

Changed

  • Adjusted guzzlehttp/promises version constraint to ^2.5
  • Adjusted guzzlehttp/psr7 version constraint to ^2.11
  • Allowed domainless SetCookie instances to be stored without wildcard request matching
  • Changed no-proxy matching to respect request ports for host-and-port rules
  • Prevented CurlMultiHandler destructors from throwing during cleanup
  • Improved invalid response handling across handlers

Deprecated

  • Deprecated non-iterable Pool request collections, which will be rejected in 8.0
  • Deprecated non-uppercase easy request methods; 8.0 preserves method casing
  • Deprecated non-string headers request option values, which will be rejected in 8.0
  • Deprecated empty headers request option value arrays, which will be rejected in 8.0
  • Deprecated empty and malformed request protocol versions, which will be rejected in 8.0
  • Deprecated conflicting raw cURL request options, including CURLOPT_SHARE, which will be rejected in 8.0
  • Deprecated scalar-coerced idn_conversion request option values, which will be rejected in 8.0
  • Deprecated invalid documented request option value types, which will be rejected in 8.0
  • Deprecated selected request options ignored by incompatible built-in handlers, which will be rejected in 8.0
  • Deprecated RequestException::wrapException(), which will be removed in 8.0
  • Deprecated RetryMiddleware::exponentialDelay(), which will be removed in 8.0

7.10.6

  • CurlMultiHandler now rejects the promise when CurlFactory::finish() throws, preserving sibling transfers
  • SetCookie now normalizes unparseable Expires values to null instead of false
  • Fix stream handler decoded gzip/deflate truncation by dropping invalid Content-Length

7.10.5

Fixed

  • Defer cURL multi cancellation cleanup until after progress callbacks return
  • Classify additional stream handler connection failures as ConnectException

7.10.4

Fixed

  • Fix IPv6 literal matching in no-proxy rules
  • Handle cURL multi completion messages without handles after cancelled transfers
  • Fix magic client request methods such as options() to uppercase inferred HTTP methods

7.10.3

Fixed

  • Fail clearly when an HTTP response header line is invalid
  • Remove middleware by name when the name is also a callable string
  • Treat empty request protocol versions as HTTP/1.1

7.10.2

Fixed

  • Normalize HTTP version request options before applying them to PSR-7 requests
  • Use string values for headers generated by request preparation and response decoding

7.10.1

Fixed

  • Fail clearly when cURL options cannot be applied
  • Fail clearly when the certificate option is malformed
  • Fail clearly when JSON decode depth is invalid
  • Fail clearly when session cookie data is malformed
  • Fail clearly when the stream progress option is not callable
  • Prevent response creation failures from exposing stale cURL responses

7.10.0

Added

  • Support for PHP 8.5

Changed

  • Adjusted guzzlehttp/promises version constraint to ^2.3
  • Adjusted guzzlehttp/psr7 version constraint to ^2.8

Does any of this look wrong? Please let us know.

Commits

See the full diff on Github. The new version differs by more commits than we can show here.

↗️ guzzlehttp/promises (indirect, 2.2.0 → 2.5.0) · Repo · Changelog

Release Notes

2.5.0

Deprecated

  • Deprecated passing non-iterable inputs to promise collection helpers and EachPromise

2.4.1

Fixed

  • Fixed cancelling settled coroutines when no current promise remains

2.4.0

Changed

  • Empty EachPromise instances now resolve when the task queue runs without wait()

2.3.1

Fixed

  • Fixed Utils::inspect() returning the internal reason array instead of the AggregateException

2.3.0

Added

  • PHP 8.5 support

Does any of this look wrong? Please let us know.

Commits

See the full diff on Github. The new version differs by 21 commits:

↗️ guzzlehttp/psr7 (indirect, 2.7.1 → 2.12.1) · Repo · Changelog

Security Advisories 🚨

🚨 guzzlehttp/psr7: CRLF Injection in HTTP Start-Line Serialization

Impact

guzzlehttp/psr7 did not reject CR/LF characters in certain first-party HTTP start-line fields: the request method, protocol version, and response reason phrase. If an application placed attacker-controlled data into one of those fields and later serialized the PSR-7 message as raw HTTP/1.x, for example with Message::toString() or an equivalent serializer, the serialized message could contain attacker-controlled header lines. The issue can also be reached through Message::parseRequest() or Message::parseResponse() when malformed raw messages are parsed into first-party PSR-7 objects and then serialized again.

Creating or modifying a Request, Response, or other PSR-7 object alone is not sufficient. The issue requires the malformed message to be serialized and written to the network, forwarded, replayed, or otherwise processed by software that does not independently reject the malformed start line. This is not the normal request-sending path used by guzzlehttp/guzzle; applications using guzzlehttp/psr7 only through Guzzle's standard HTTP client APIs are not expected to be affected.

Applications are most likely to be affected when they manually serialize PSR-7 messages, forward raw HTTP messages, or use custom transports, proxying, crawling, webhook delivery, testing, or similar code. Depending on how downstream HTTP/1.1 components parse the serialized message, this may lead to header injection, response splitting, request smuggling, or cache poisoning.

Patches

The issue is patched in 2.12.1 and later. Starting in that release, guzzlehttp/psr7 rejects CR/LF characters in HTTP method, protocol version, and response reason phrase values before storing them in first-party message objects.

Workarounds

If you cannot upgrade immediately, reject CR/LF in untrusted method, protocol version, and reason phrase values before constructing or modifying PSR-7 messages.

Applications that parse, forward, replay, or serialize raw HTTP messages cannot work around the parser entry points by validating only after parsing. They should validate the raw start line before calling Message::parseRequest() or Message::parseResponse(), avoid reparsing untrusted raw messages, or upgrade. If an application runs with attacker-controlled synthetic $_SERVER values, validate REQUEST_METHOD and SERVER_PROTOCOL before calling ServerRequest::fromGlobals().

🚨 guzzlehttp/psr7 has CRLF Injection via URI Host Component

Impact

guzzlehttp/psr7 did not reject ASCII control characters, whitespace, or DEL in first-party URI host components. The issue requires a PSR-7 request to be serialized into a raw HTTP/1.x message, for example with GuzzleHttp\Psr7\Message::toString() or an equivalent custom serializer. Creating a Uri, Request, or other PSR-7 object alone is not sufficient. The malformed host must be copied into the serialized Host header without further validation.

A vulnerable flow is:

  1. An application accepts a user-controlled URL.
  2. The URL is used to construct a PSR-7 Uri or Request.
  3. The host component contains CRLF or another header-unsafe character.
  4. The request is serialized into a raw HTTP/1.x message without an explicit Host header.
  5. The host is copied into the serialized Host header.
  6. The serialized request is written to the network or otherwise processed by software that does not independently reject the malformed host.

In that flow, an attacker can cause the serialized request to contain additional attacker-controlled header lines. For example, a host containing "\r\nX-Injected: yes" can cause the generated Host header to span multiple HTTP header lines.

This is not the normal request-sending path used by guzzlehttp/guzzle. Applications using guzzlehttp/psr7 only through Guzzle's standard HTTP client APIs are not expected to be affected. Applications are most likely to be affected when they manually serialize PSR-7 requests, forward raw HTTP messages, or use custom transports, proxying, crawling, webhook delivery, or similar request-dispatch code that serializes requests without independently validating URI hosts and header data. In deployments involving HTTP/1.1 connection reuse, proxies, gateways, or load balancers, this malformed serialized request may also contribute to request smuggling or cache poisoning, depending on how downstream components parse the request.

Patches

The issue is patched in 2.10.2 and later. 1.x is end-of-life and will not receive a patch.

Workarounds

If you cannot upgrade immediately, validate and reject all untrusted URI strings before constructing PSR-7 Uri or Request instances. Reject input containing ASCII control characters, whitespace, or DEL, including CRLF, tab, space, NUL, or DEL characters:

if (preg_match('/[\x00-\x20\x7F]/', $untrustedUrl)) {
    throw new \InvalidArgumentException('Insecure URL detected');
}

Applications that manually serialize or forward requests should also ensure the final HTTP client, transport, or serializer rejects invalid URI and header data before writing requests to the network.

References

🚨 guzzlehttp/psr7 has Host Confusion via Authority Reinterpretation

Impact

guzzlehttp/psr7 improperly interpreted malformed Host header values when constructing request URIs from inbound request data. This issue concerns inbound request parsing and server request construction. It does not require serializing a PSR-7 request, and it is not part of the normal outbound request-sending path used by guzzlehttp/guzzle.

A vulnerable flow is:

  1. An attacker controls a raw HTTP request or server variable containing a Host value.
  2. The Host value contains URI authority delimiters, such as trusted.example@evil.example.
  3. guzzlehttp/psr7 uses that value to construct a URI.
  4. The URI parser treats the portion before @ as userinfo and the portion after @ as the URI host.
  5. The resulting PSR-7 request URI host differs from the original Host header value.

For example, Host: trusted.example@evil.example can result in a PSR-7 URI whose host is evil.example, while the original Host header value remains trusted.example@evil.example.

Applications are affected if they parse attacker-controlled raw HTTP requests with GuzzleHttp\Psr7\Message::parseRequest() or the legacy 1.x GuzzleHttp\Psr7\parse_request() function, or if they build server requests from attacker-controlled server variables with GuzzleHttp\Psr7\ServerRequest::fromGlobals() or GuzzleHttp\Psr7\ServerRequest::getUriFromGlobals(), and then rely on the resulting URI host for routing, allow-list checks, credential selection, or forwarding decisions. Applications using guzzlehttp/psr7 only through Guzzle's standard HTTP client APIs are not expected to be affected. In affected forwarding or gateway scenarios, this may cause requests or credentials to be sent to an unintended host.

Patches

The issue is patched in 2.10.2 and later. 1.x is end-of-life and will not receive a patch.

Workarounds

If you cannot upgrade immediately, validate Host values before passing untrusted request data to Message::parseRequest(), legacy 1.x parse_request(), ServerRequest::fromGlobals(), or ServerRequest::getUriFromGlobals().

Accept only uri-host [ ":" port ]. Reject values containing whitespace, control characters, userinfo (@), path (/ or \), query (?), fragment (#), malformed IP literals or bracket syntax, or invalid port syntax.

Do not validate Host by prefixing it with http:// and passing it to parse_url(), because that can reinterpret malformed values as URI userinfo and host.

References

Release Notes

2.12.1

Security

2.12.0

Deprecated

  • Deprecated non-finite float values in Query::build() that guzzlehttp/psr7 3.0 rejects
  • Deprecated non-finite float multipart contents that guzzlehttp/psr7 3.0 rejects
  • Deprecated non-string scalar bodies in Utils::streamFor(); cast them to a string for 3.0
  • Deprecated non-string Uri::withQueryValues() values; cast them to a string for 3.0

2.11.0

Changed

  • Changed Utils::modifyRequest() to reject conflicting URI and Host header changes in the same call
  • Changed Header::parse() to split semicolon-separated parameters without repeated regular expression lookaheads
  • Changed UriComparator::isCrossOrigin() so only HTTP and HTTPS missing ports receive implicit default ports

Deprecated

  • Deprecated invalid PSR-7 arguments that guzzlehttp/psr7 3.0 will require native types for
  • Deprecated non-string header values that guzzlehttp/psr7 3.0 will reject
  • Deprecated empty header value arrays that guzzlehttp/psr7 3.0 will reject
  • Deprecated URI schemes that do not match guzzlehttp/psr7 3.0 syntax requirements
  • Deprecated multipart boundary and custom part header metadata that guzzlehttp/psr7 3.0 will reject
  • Deprecated reliance on automatic uppercasing of request methods; guzzlehttp/psr7 3.0 preserves method casing
  • Deprecated invalid Utils::modifyRequest() change values that guzzlehttp/psr7 3.0 will reject

Fixed

  • Fixed Utils::copyToStream() to retry short destination writes instead of dropping the unwritten remainder
  • Fixed Header::parse() splitting of semicolon-separated parameters with escaped quotes

2.10.4

Fixed

  • Apply UriNormalizer percent-encoding normalizations to URI fragments
  • Make LimitStream::getSize() return 0 for slices past the underlying stream end
  • Make AppendStream::read() return an empty string when no streams are attached
  • Make CachingStream::read() throw on an incomplete cache-target write instead of silently corrupting replays
  • Prevent CachingStream::seek() from looping indefinitely when the remote stream makes no progress

2.10.3

Fixed

  • Fixed URI parsing for IPv6 literals containing embedded IPv4 addresses
  • Fixed malformed UTF-8 URI strings being parsed as empty URIs

2.10.2

Security

Fixed

  • Make ServerRequest::fromGlobals() robust against unexpected HTTP header value types in $_SERVER

2.10.1

Fixed

  • Fix Utils::modifyRequest() with numeric header names

2.10.0

  • Harden ServerRequest::fromGlobals() against malformed $_SERVER values
  • Prevent custom stream metadata from affecting internal size handling
  • Throw when StreamWrapper::getResource() cannot create a resource
  • Preserve custom request implementations in Utils::modifyRequest()
  • Preserve custom URI implementations in UriResolver::resolve()
  • Make Uri::__toString() side-effect-free

2.9.1

  • Fix parsing of relative path references containing a colon in a non-initial path segment
  • Fix CachingStream::detach() returning an incomplete resource before the decorated stream has been fully read
  • Fix Message::bodySummary() returning null when truncating printable UTF-8 bodies inside a multibyte character

2.9.0

Added

  • Added nested array expansion support to MultipartStream
  • Added @return static to MessageTrait methods

Changed

  • Updated MIME type mappings

See also the change log for changes.

2.8.1

Fixed

  • Encode + signs in Uri::withQueryValue() and Uri::withQueryValues() to prevent them being interpreted as spaces

See also the change log for changes.

2.8.0

Added

  • Allow empty lists as header values

Changed

  • PHP 8.5 support

See also the change log for changes.

Does any of this look wrong? Please let us know.

Commits

See the full diff on Github. The new version differs by more commits than we can show here.


Depfu Status

Depfu will automatically keep this PR conflict-free, as long as you don't add any commits to this branch yourself. You can also trigger a rebase manually by commenting with @depfu rebase.

All Depfu comment commands
@​depfu rebase
Rebases against your default branch and redoes this update
@​depfu recreate
Recreates this PR, overwriting any edits that you've made to it
@​depfu merge
Merges this PR once your tests are passing and conflicts are resolved
@​depfu cancel merge
Cancels automatic merging of this PR
@​depfu close
Closes this PR and deletes the branch
@​depfu reopen
Restores the branch and reopens this PR (if it's closed)
@​depfu pause
Ignores all future updates for this dependency and closes this PR
@​depfu pause [minor|major]
Ignores all future minor/major updates for this dependency and closes this PR
@​depfu resume
Future versions of this dependency will create PRs again (leaves this PR as is)

@depfu depfu Bot added the depfu label Jun 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants