CVE-2026-67339: Guzzle Proxy-Authorization Headers Can Be Sent Vulnerability

MODERATE
Advisory Identifier: GHSA-94pj-82f3-465w
CVSS 5.3
CWE-522 CWE-200 CWE-201
Published
Advisory Summary

CVE-2026-67339 is a MODERATE (CVSS 5.3) proxy-authorization headers can be sent vulnerability (CWE-522: Insufficiently Protected Credentials) affecting Guzzle libraries in the Packagist ecosystem. The issue involves proxy-authorization headers can be sent to origin servers. Remediation is available by upgrading affected packages to version 7.14.2.

CVE-2026-67339 at a Glance

CVE Identifier CVE-2026-67339
GHSA Identifier GHSA-94pj-82f3-465w
Severity MODERATE
CVSS v3.1 Base Score 5.3
CWE Classification CWE-522: Insufficiently Protected Credentials
Affected Product Guzzle
Package Ecosystem Packagist
Published Date
Last Updated

Security Impact

CVSS: 5.3

The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N).

Attack Vector Network (AV:N)
Attack Complexity Low (AC:L)
Privileges Required None (PR:N)
User Interaction None (UI:N)
Scope Unchanged (S:U)
Confidentiality Low (C:L)
Integrity None (I:N)
Availability None (A:N)

How to Fix CVE-2026-67339

To remediate this vulnerability, upgrade all affected Guzzle dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

guzzlehttp/guzzle fixed: 7.14.2
Upgrade guzzlehttp/guzzle to 7.14.2
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

inspect dependencies for guzzlehttp/guzzle

How to Check if You Are Affected

To determine whether your application is affected by CVE-2026-67339, inspect your project dependencies for Guzzle:

inspect dependencies for guzzlehttp/guzzle

Analyze the terminal output to locate any version of Guzzle in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 7.14.2), your application is affected.

Note: Verify declared build manifests and deployed runtime container environments.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-522: Insufficiently Protected Credentials, where the product transmits or stores authentication credentials, but it uses an insecure method that is susceptible to unauthorized interception and/or retrieval. In Guzzle, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

### Impact In affected versions, the built-in cURL handlers (`CurlHandler` and `CurlMultiHandler`) put every first-class request header in cURL's origin header list (`CURLOPT_HTTPHEADER`). These handlers are the default when the PHP cURL extension is available. They move `Proxy-Authorization` to the proxy-only list (`CURLOPT_PROXYHEADER`) only when Guzzle predicts an HTTP or HTTPS proxy. A "first-class" header is part of the normal request message and can be set on a PSR-7 request, through client `headers` defaults, the `headers` request option, or middleware. It does not include a literal line supplied through raw `CURLOPT_HTTPHEADER`, `CURLOPT_PROXYHEADER`, or `stream_context.http.header` controls. Because that migration follows Guzzle's prediction rather than the route libcurl actually takes, the credential stays in the origin list and is sent to the origin server when a request is: - direct, including `proxy` set to `''` to disable proxying. - bypassed by a `no`, `no_proxy`, or `NO_PROXY` match. - sent through a SOCKS proxy, which does not use the HTTP proxy header channel. - redirected from a safely proxied hop into any of those routes: redirect middleware re-evaluates the proxy per hop but, unlike `Authorization` and `Cookie`, does not strip `Proxy-Authorization` cross-origin. On installations whose libcurl is older than 7.37.0, or whose PHP cURL extension lacks `CURLOPT_PROXYHEADER`, `CURLOPT_HEADEROPT`, and `CURLHEADER_SEPARATE`, no proxy-only channel is available, so cURL left the header in the origin list for every route. The stream handler also serialized first-class values before selecting a proxy. PHP removes only the first `Proxy-Authorization` line from CONNECT, so another first-class value or a URL-userinfo Basic line could reach the tunneled origin. A later raw `stream_context.http.proxy` override could instead reroute either credential directly to the origin. The disclosed value is a private credential meant only for the proxy. RFC 9110 defines `Proxy-Authorization` as credentials for the next inbound proxy, and an origin is never an intended recipient. The flaw can silently give a working proxy credential to an unrelated third party. In the worst case, an attacker controls the origin and records the credential through access logs, tracing systems, or application logs. If it remains valid, the attacker can abuse a paid or access-controlled proxy, impersonate the proxy principal, or reach destinations the proxy is trusted to reach. A strong remote exploit is possible when an application sends a request to an attacker-controlled HTTP URL through a proxy with a default `Proxy-Authorization` header, then follows the attacker's redirect to an HTTPS or no-proxy destination that Guzzle reaches directly. Using a first-class `Proxy-Authorization` header is a legitimate, documented configuration, so affected applications are not misusing the library. Guzzle does not create this field, so applications that never configure one are unaffected by the first-class-header flaw. Proxy URL userinfo is not affected on its own, but the stream handler could expose its Basic line when combined with a first-class field or a later raw `stream_context.http.proxy` override. `CURLOPT_PROXYUSERPWD` is unaffected. Literal lines supplied through raw `CURLOPT_HTTPHEADER`, `CURLOPT_PROXYHEADER`, or `stream_context.http.header` remain caller-controlled and outside the first-class-header guarantee. ### Patches The issue is fixed in `7.14.2`. The cURL handlers keep first-class `Proxy-Authorization` values out of the origin header list. When proxy header separation is available, they pass the values through `CURLOPT_PROXYHEADER` with `CURLHEADER_SEPARATE`. An empty value uses cURL's semicolon form to suppress credentials from proxy URL userinfo. On older builds, Guzzle drops the field for direct, bypassed, and SOCKS routes, but fails before network I/O if the request might use an HTTP or HTTPS proxy. The stream handler removes the field from origin headers before choosing a route. If it selects a proxy, it accepts one value, including empty, writes a validated proxy header, and gives that value precedence over proxy URL userinfo. Multiple values, line breaks, and raw proxy overrides that could reroute generated credentials fail before connection. Direct and bypassed requests drop the field. Versions before `7.14.2` are affected by these origin-bound credential paths. ### Workarounds If you cannot upgrade immediately, remove first-class `Proxy-Authorization` fields from requests, client defaults, and middleware. Supply proxy credentials instead through proxy URL userinfo, for example `http://user:pass@proxy.example:8080`, or use `CURLOPT_PROXYUSERPWD` with the cURL handlers. Do not combine proxy URL userinfo with a first-class field or a raw `stream_context.http.proxy` override. If a first-class field is unavoidable, use libcurl 7.37.0 or newer with `CURLOPT_PROXYHEADER`, `CURLOPT_HEADEROPT`, and `CURLHEADER_SEPARATE`, and ensure the field is never present on a client that can issue direct, bypassed, or SOCKS requests or follow redirects into those routes. A newer libcurl is necessary but does not fix Guzzle's route-dependent migration by itself, and disabling redirects reduces but does not eliminate exposure. ### References * https://www.rfc-editor.org/rfc/rfc9110.html#section-11.7.2 * https://curl.se/libcurl/c/CURLOPT_PROXYHEADER.html * https://curl.se/libcurl/c/CURLOPT_HEADEROPT.html * https://curl.se/libcurl/c/CURLOPT_HTTPHEADER.html

CVE-2026-67339 Affected Guzzle Versions

1 component(s)
Fixed Versions:
7.14.2
Product / Package Ecosystem Affected Versions Fixed Version
guzzlehttp/guzzle
Packagist
< 7.14.2
7.14.2

References

Frequently Asked Questions

What is CVE-2026-67339?
CVE-2026-67339 is a security vulnerability in Guzzle involving Proxy-Authorization headers can be sent to origin servers under CWE-522: Insufficiently Protected Credentials.
Which Guzzle versions are affected?
Affected versions include releases prior to 7.14.2 across affected packages: guzzlehttp/guzzle.
What version fixes CVE-2026-67339?
Upgrading to 7.14.2 (or the latest patched release for your respective branch) resolves the vulnerability.
Is guzzlehttp/guzzle affected?
Yes, guzzlehttp/guzzle is affected in releases prior to 7.14.2. Upgrade your dependency to 7.14.2 or later.
What is the CVSS score of CVE-2026-67339?
CVE-2026-67339 has a CVSS v3.1 base score of 5.3 (MODERATE) with vector string CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N.
What CWE is associated with CVE-2026-67339?
CVE-2026-67339 is classified under CWE-522: Insufficiently Protected Credentials (The product transmits or stores authentication credentials, but it uses an insecure method that is susceptible to unauthorized interception and/or retrieval.).
How can I check Packagist dependencies for CVE-2026-67339?
Run the dependency tree command: 'inspect dependencies for guzzlehttp/guzzle'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-94pj-82f3-465w",
  "modified" : "2026-08-04T12:49:56Z",
  "published" : "2026-07-20T21:46:02Z",
  "aliases" : [ "CVE-2026-67339" ],
  "summary" : "Guzzle: Proxy-Authorization headers can be sent to origin servers",
  "details" : "### Impact\n\nIn affected versions, the built-in cURL handlers (`CurlHandler` and `CurlMultiHandler`) put every first-class request header in cURL's origin header list (`CURLOPT_HTTPHEADER`). These handlers are the default when the PHP cURL extension is available. They move `Proxy-Authorization` to the proxy-only list (`CURLOPT_PROXYHEADER`) only when Guzzle predicts an HTTP or HTTPS proxy. A \"first-class\" header is part of the normal request message and can be set on a PSR-7 request, through client `headers` defaults, the `headers` request option, or middleware. It does not include a literal line supplied through raw `CURLOPT_HTTPHEADER`, `CURLOPT_PROXYHEADER`, or `stream_context.http.header` controls.\n\nBecause that migration follows Guzzle's prediction rather than the route libcurl actually takes, the credential stays in the origin list and is sent to the origin server when a request is:\n\n- direct, including `proxy` set to `''` to disable proxying.\n- bypassed by a `no`, `no_proxy`, or `NO_PROXY` match.\n- sent through a SOCKS proxy, which does not use the HTTP proxy header channel.\n- redirected from a safely proxied hop into any of those routes: redirect middleware re-evaluates the proxy per hop but, unlike `Authorization` and `Cookie`, does not strip `Proxy-Authorization` cross-origin.\n\nOn installations whose libcurl is older than 7.37.0, or whose PHP cURL extension lacks `CURLOPT_PROXYHEADER`, `CURLOPT_HEADEROPT`, and `CURLHEADER_SEPARATE`, no proxy-only channel is available, so cURL left the header in the origin list for every route. The stream handler also serialized first-class values before selecting a proxy. PHP removes only the first `Proxy-Authorization` line from CONNECT, so another first-class value or a URL-userinfo Basic line could reach the tunneled origin. A later raw `stream_context.http.proxy` override could instead reroute either credential directly to the origin.\n\nThe disclosed value is a private credential meant only for the proxy. RFC 9110 defines `Proxy-Authorization` as credentials for the next inbound proxy, and an origin is never an intended recipient. The flaw can silently give a working proxy credential to an unrelated third party. In the worst case, an attacker controls the origin and records the credential through access logs, tracing systems, or application logs. If it remains valid, the attacker can abuse a paid or access-controlled proxy, impersonate the proxy principal, or reach destinations the proxy is trusted to reach. A strong remote exploit is possible when an application sends a request to an attacker-controlled HTTP URL through a proxy with a default `Proxy-Authorization` header, then follows the attacker's redirect to an HTTPS or no-proxy destination that Guzzle reaches directly.\n\nUsing a first-class `Proxy-Authorization` header is a legitimate, documented configuration, so affected applications are not misusing the library. Guzzle does not create this field, so applications that never configure one are unaffected by the first-class-header flaw. Proxy URL userinfo is not affected on its own, but the stream handler could expose its Basic line when combined with a first-class field or a later raw `stream_context.http.proxy` override. `CURLOPT_PROXYUSERPWD` is unaffected. Literal lines supplied through raw `CURLOPT_HTTPHEADER`, `CURLOPT_PROXYHEADER`, or `stream_context.http.header` remain caller-controlled and outside the first-class-header guarantee.\n\n### Patches\n\nThe issue is fixed in `7.14.2`. The cURL handlers keep first-class `Proxy-Authorization` values out of the origin header list. When proxy header separation is available, they pass the values through `CURLOPT_PROXYHEADER` with `CURLHEADER_SEPARATE`. An empty value uses cURL's semicolon form to suppress credentials from proxy URL userinfo. On older builds, Guzzle drops the field for direct, bypassed, and SOCKS routes, but fails before network I/O if the request might use an HTTP or HTTPS proxy.\n\nThe stream handler removes the field from origin headers before choosing a route. If it selects a proxy, it accepts one value, including empty, writes a validated proxy header, and gives that value precedence over proxy URL userinfo. Multiple values, line breaks, and raw proxy overrides that could reroute generated credentials fail before connection. Direct and bypassed requests drop the field. Versions before `7.14.2` are affected by these origin-bound credential paths.\n\n### Workarounds\n\nIf you cannot upgrade immediately, remove first-class `Proxy-Authorization` fields from requests, client defaults, and middleware. Supply proxy credentials instead through proxy URL userinfo, for example `http://user:pass@proxy.example:8080`, or use `CURLOPT_PROXYUSERPWD` with the cURL handlers. Do not combine proxy URL userinfo with a first-class field or a raw `stream_context.http.proxy` override. If a first-class field is unavoidable, use libcurl 7.37.0 or newer with `CURLOPT_PROXYHEADER`, `CURLOPT_HEADEROPT`, and `CURLHEADER_SEPARATE`, and ensure the field is never present on a client that can issue direct, bypassed, or SOCKS requests or follow redirects into those routes. A newer libcurl is necessary but does not fix Guzzle's route-dependent migration by itself, and disabling redirects reduces but does not eliminate exposure.\n\n### References\n\n* https://www.rfc-editor.org/rfc/rfc9110.html#section-11.7.2\n* https://curl.se/libcurl/c/CURLOPT_PROXYHEADER.html\n* https://curl.se/libcurl/c/CURLOPT_HEADEROPT.html\n* https://curl.se/libcurl/c/CURLOPT_HTTPHEADER.html",
  "severity" : [ {
    "type" : "CVSS_V3",
    "score" : "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "Packagist",
      "name" : "guzzlehttp/guzzle"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0"
      }, {
        "fixed" : "7.14.2"
      } ]
    } ]
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/guzzle/guzzle/security/advisories/GHSA-94pj-82f3-465w"
  }, {
    "type" : "ADVISORY",
    "url" : "https://nvd.nist.gov/vuln/detail/CVE-2026-67339"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/guzzle/guzzle/pull/3876"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/guzzle/guzzle/commit/9e4580d4b9981e903dc6323fe37f50a96e85b05e"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/guzzle/guzzle"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/guzzle/guzzle/releases/tag/7.14.2"
  }, {
    "type" : "WEB",
    "url" : "https://www.vulncheck.com/advisories/guzzlehttp-guzzle-before-proxy-authorization-header-disclosure"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-200", "CWE-201", "CWE-522" ],
    "severity" : "MODERATE",
    "github_reviewed" : true,
    "github_reviewed_at" : "2026-07-20T21:46:02Z",
    "nvd_published_at" : null
  }
}