Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-59882

CVE-2026-59882: guzzlehttp/psr7 Information Disclosure

CVE-2026-59882 is an information disclosure vulnerability in guzzlehttp/psr7 that allows URI host parsing discrepancies affecting security decisions. This post covers technical details, affected versions, and mitigation.

Published:

CVE-2026-59882 Overview

CVE-2026-59882 affects guzzlehttp/psr7, a widely used PSR-7 HTTP message library implementation for PHP. The Uri::assertValidHost() method fails to reject URI host components containing authority delimiters, embedded ports, or malformed IPv6 brackets. As a result, Uri::getHost() can return a value that disagrees with the URI authority used for downstream security or routing decisions. Attackers can craft URIs where the parsed host differs from the effective destination, enabling server-side request forgery (SSRF) filter bypasses, access control evasion, or request routing confusion. The issue is categorized under [CWE-436] Interpretation Conflict and is fixed in version 2.12.3.

Critical Impact

Applications relying on Uri::getHost() for allowlisting, SSRF prevention, or authorization decisions may forward requests to attacker-controlled destinations while believing the host is trusted.

Affected Products

  • guzzlehttp/psr7 PHP library versions prior to 2.12.3
  • PHP applications using guzzlehttp/psr7 for URI parsing and validation
  • Downstream frameworks and HTTP clients depending on guzzlehttp/psr7 (including Guzzle HTTP client)

Discovery Timeline

  • 2026-07-08 - CVE-2026-59882 published to NVD
  • 2026-07-08 - Last updated in NVD database

Technical Details for CVE-2026-59882

Vulnerability Analysis

The vulnerability is an interpretation conflict [CWE-436] in URI parsing. The Uri::assertValidHost() method in guzzlehttp/psr7 accepts host strings that contain characters reserved for other URI authority components. These include @ (userinfo delimiter), : (port delimiter), /, ?, #, and improperly bracketed IPv6 literals.

When a crafted URI passes validation, Uri::getHost() returns a normalized host that does not match how the full authority is interpreted by an HTTP client, proxy, or downstream parser. Security controls that inspect only the return value of getHost() operate on a different value than the code that actually issues the request.

Exploitation typically requires user interaction with a crafted URL and high attack complexity, but the impact is meaningful in SSRF-sensitive contexts such as webhook processors, URL previewers, and OAuth redirect validators.

Root Cause

The regular expression used to preserve bracketed IPv6 literals was overly permissive. It matched any characters inside brackets, allowing embedded control characters, delimiters, and structural URI metacharacters to pass through host validation without rejection.

Attack Vector

An attacker supplies a URL where the host component embeds authority delimiters or malformed IPv6 brackets. The application calls Uri::getHost() to check the host against an allowlist. The check passes because the parsed host appears legitimate. When the URI is later serialized or dispatched, the full authority resolves to a different, attacker-controlled destination.

php
// Security patch in src/Uri.php - Validate URI host so getHost() matches the URI authority (#811)
// Preserve bracketed IPv6 literals before encoding, including dotted IPv4 tails.
$prefix = '';
-$ipv6Prefix = preg_match('%\A([0-9A-Za-z+.-]+://\[[0-9:.a-fA-F]+\])(.*)\z%s', $url, $matches);
+$ipv6Prefix = preg_match('%\A([0-9A-Za-z+.-]+://\[[^\]\\x00-\\x20/?#@]+\])(.*)\z%s', $url, $matches);

if ($ipv6Prefix === false) {
    return false;
}

Source: guzzle/psr7 commit ddd64f1. The patched regex explicitly excludes null bytes, control characters, whitespace, and authority delimiters (/, ?, #, @) inside IPv6 brackets, forcing malformed hosts to be rejected.

Detection Methods for CVE-2026-59882

Indicators of Compromise

  • Outbound HTTP requests from application servers to unexpected internal IP ranges or cloud metadata endpoints such as 169.254.169.254.
  • Application logs showing URIs where Uri::getHost() output differs from the destination recorded by the HTTP client or reverse proxy.
  • URL inputs containing @ characters, embedded : port specifiers, or IPv6 brackets combined with additional structural characters.

Detection Strategies

  • Perform software composition analysis (SCA) to identify PHP projects with guzzlehttp/psr7 versions below 2.12.3 in composer.lock.
  • Log and compare parsed host values against the final resolved destination host at the HTTP client layer to surface interpretation mismatches.
  • Instrument URI validation code paths to alert when hosts contain non-standard characters, particularly @, unbracketed :, or malformed IPv6 literals.

Monitoring Recommendations

  • Monitor outbound egress from application tiers for connections to RFC1918, link-local, and cloud metadata address space.
  • Track dependency inventories continuously and alert when vulnerable versions of guzzlehttp/psr7 are detected in production builds.
  • Review web application firewall (WAF) logs for suspicious URL parameters submitted to endpoints that accept user-controlled URIs.

How to Mitigate CVE-2026-59882

Immediate Actions Required

  • Upgrade guzzlehttp/psr7 to version 2.12.3 or later using composer update guzzlehttp/psr7.
  • Audit application code that calls Uri::getHost() for security decisions, including SSRF allowlists and OAuth redirect validation.
  • Rebuild and redeploy container images and application artifacts to ensure the patched library is loaded at runtime.

Patch Information

The fix is available in guzzle/psr7 release 2.12.3. The patch is implemented in pull request #811 and detailed in GitHub Security Advisory GHSA-c2w2-prh8-qm98. The change tightens the IPv6 bracket regex and adds validation rejecting authority delimiters embedded in host components.

Workarounds

  • Add defense-in-depth URL validation before passing values to guzzlehttp/psr7, rejecting inputs containing @, control characters, or non-hex data inside IPv6 brackets.
  • Enforce egress network controls that restrict application servers from reaching internal IP ranges and cloud metadata services.
  • Where feasible, resolve and validate hostnames against an allowlist after full URI parsing, comparing against the destination used by the HTTP client rather than trusting Uri::getHost() alone.
bash
# Upgrade guzzlehttp/psr7 to patched version
composer require guzzlehttp/psr7:^2.12.3
composer update guzzlehttp/psr7

# Verify installed version
composer show guzzlehttp/psr7 | grep versions

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.