GHSA-H95V-H523-3MW8: Root-cause fix for Referer fragment leakage in Guzzle redirects
Summary
The security-relevant change for GHSA-H95V-H523-3MW8 is a direct fix in redirect Referer generation: Guzzle now strips URI fragments in addition to userinfo before emitting a Referer header during automatic redirects. The patch aligns implementation, tests, changelog, and request-option documentation. The same pull request also contains unrelated cookie-scope hardening, but that is orthogonal to this advisory.
Analysis
Vulnerability
GHSA-H95V-H523-3MW8 describes a redirect-handling flaw in Guzzle where client-side URI fragments could be copied into generated Referer headers when redirects were followed with referer tracking enabled. Fragments are not intended to be transmitted to servers as part of normal HTTP request targeting, and applications commonly place bearer material or other sensitive state in the fragment component. If redirect middleware serializes the full original URI into Referer, that client-side data becomes server-visible and may propagate into logs, analytics, or downstream services.
The vulnerable implementation in src/RedirectMiddleware.php only removed userinfo before constructing the header, leaving the fragment intact. The request-options documentation also lacked the fragment-exclusion guarantee before the patch. The advisory and patch references are the authoritative sources: pull request #3901 and the GitHub security advisory. A secondary summary is available at cvereports.com.
// Vulnerable behavior in RedirectMiddleware.php
$uri = $request->getUri()->withUserInfo('');Patch
The patch changes Referer construction to explicitly clear the fragment in addition to userinfo:
// Patched behavior in RedirectMiddleware.php
$uri = $request->getUri()->withUserInfo('')->withFragment('');This is the correct normalization point for the bug because the leak originates in header generation, not in redirect policy generally. The patch is reinforced by a targeted test update in tests/RedirectMiddlewareTest.php, which now uses an input URI containing a fragment and asserts that the generated Referer value excludes it:
$request = new Request('GET', 'http://example.com/path?a=b#secret');
'http://example.com/path?a=b',Documentation was also updated in docs/request-options.md to state that generated Referer values exclude user information and fragments, and that the header is omitted on scheme changes. The changelog explicitly records the security fix: “Exclude URI fragments from Referer headers generated for redirects.” These changes are visible in the upstream patch.
Notably, the same pull request also includes cookie host-only persistence and identity fixes across CookieJar, FileCookieJar, SessionCookieJar, and SetCookie. Those changes appear security-relevant in their own right, but they are separate from the Referer-fragment disclosure issue identified by this advisory.
Review
Pros
- The implementation change is minimal and directly addresses the root cause: fragment data was not stripped before serializing the source URI into a Referer header.
- The fix is placed in the correct code path,
RedirectMiddleware, which centralizes auto-redirect Referer generation. - The regression test is well targeted: it introduces a URI with a fragment and verifies the emitted Referer omits
#secret. - Documentation and changelog updates match the code change, reducing ambiguity for users who rely on
allow_redirects.referer. - The documented behavior remains aligned with privacy expectations for Referer generation by excluding both userinfo and fragments.
Cons
- The pull request mixes this advisory fix with unrelated cookie-jar hardening, which increases review surface and can complicate backporting or risk assessment for teams only addressing GHSA-H95V-H523-3MW8.
- Based on the provided snippets, test coverage is focused on the positive fragment-removal case; broader matrix coverage for redirect status codes or cross-scheme suppression is not shown here, though the docs mention scheme-change omission.
- The patch does not appear to add a dedicated helper or explicit comment around Referer sanitization semantics, so future regressions would still rely primarily on tests and documentation.
Verdict
Root-cause.
The security fix for GHSA-H95V-H523-3MW8 is a direct remediation of the actual leakage mechanism: the middleware now removes the fragment before generating the Referer header. This is not a workaround or policy bypass; it corrects the canonicalization logic at the point where sensitive client-side URI state was being exposed. The accompanying test demonstrates the intended behavior concretely, and the docs/changelog updates make the contract explicit. Engineers should note that the same upstream pull request also contains separate cookie handling changes, but those do not weaken the conclusion that the Referer-fragment issue itself is properly fixed in the patch.
Recommended Labs
Try this vulnerability pattern yourself with hands-on labs.
- Energy.php
Closest hands-on defensive match in PHP for the disclosure aspect of this Guzzle issue. The advisory is about sensitive data leaking through request metadata (Referer headers during redirects); this lab focuses on preventing information disclosure, which reinforces the same mitigation mindset: avoid exposing secrets through secondary channels and harden defensive handling around outbound/inbound error and metadata flows.
- SSRF.php
Good supporting PHP lab because the vulnerable component is an HTTP client handling redirects and outbound requests. While SSRF is a different weakness, this lab builds practical defensive instincts for securing server-side HTTP request behavior, validating destinations, and reasoning about redirect-related risk in HTTP client code.
- Capital0.php
A harder follow-on lab for deeper practice with unsafe server-side request flows in PHP. Recommended as an advanced companion once the easier SSRF lab is complete, because the Guzzle patch topic also benefits from understanding defense-in-depth around outbound requests, redirects, trust boundaries, and unintended data exposure paths.