Vulnerability details

7.4/10
CVSS 3.1
GHSA-fmxf-pm6p-7xgm
resolved Published 2026-05-18 Updated 2026-06-09
Vulnerability Data from Dependency-Track
Description
## Summary async-http-client leaks `Cookie` headers to cross-origin redirect targets. When following a redirect across a security boundary (different origin, or HTTPS→HTTP downgrade), the `propagatedHeaders()` method in `Redirect30xInterceptor.java` strips `Authorization` and `Proxy-Authorization` headers but does not strip `Cookie`, so session cookies and other sensitive cookie values are forwarded to the redirect target — which may be attacker-controlled. ## Details The vulnerability is in `client/src/main/java/org/asynchttpclient/netty/handler/intercept/Redirect30xInterceptor.java`. The caller computes `stripAuth` on each redirect: ```java boolean sameBase = request.getUri().isSameBase(newUri); boolean stripAuth = !sameBase || schemeDowngrade || stripAuthorizationOnRedirect; // ... requestBuilder.setHeaders(propagatedHeaders(request, realm, keepBody, stripAuth)); ``` `stripAuth` is `true` whenever the redirect crosses an origin, downgrades the scheme, or the caller opted in via `AsyncHttpClientConfig#isStripAuthorizationOnRedirect()`. In the vulnerable version, `propagatedHeaders()` only removes `Authorization` and `Proxy-Authorization` in that branch — `Cookie` is left untouched: ```java private static HttpHeaders propagatedHeaders(Request request, Realm realm, boolean keepBody, boolean stripAuthorization) { HttpHeaders headers = request.getHeaders() .remove(HOST) .remove(CONTENT_LENGTH); if (!keepBody) { headers.remove(CONTENT_TYPE); } if (stripAuthorization || (realm != null && (realm.getScheme() == AuthScheme.NTLM || realm.getScheme() == AuthScheme.SCRAM_SHA_256))) { headers.remove(AUTHORIZATION) .remove(PROXY_AUTHORIZATION); // BUG: COOKIE is not removed here, so cookies leak across the security boundary. } return headers; } ``` The companion test class `RedirectCredentialSecurityTest` covers `Authorization` / `Proxy-Authorization` stripping on cross-origin redirects and scheme downgrades, but has no coverage for `Cookie`, which is why the regression went unnoticed. ## Proof of concept ```java import org.asynchttpclient.*; AsyncHttpClient client = asyncHttpClient(); // trusted-api.com responds 302 -> https://evil.com Request request = new RequestBuilder("GET") .setUrl("https://trusted-api.com/endpoint") .setHeader("Cookie", "session=abc123; csrf=xyz789; api_key=secret") .setHeader("Authorization", "Bearer token123") .build(); client.executeRequest(request).get(); // Request seen by evil.com after the redirect: // Authorization: <stripped> // Cookie: session=abc123; csrf=xyz789; api_key=secret <-- leaked ``` ## Impact - **Session hijacking** — leaked session cookies allow impersonation. - **CSRF token theft** — CSRF tokens carried in cookies are disclosed. - **API key theft** — API keys stored in cookies are disclosed. - **Privacy** — tracking identifiers leak to third-party origins. Realistic attack paths: - Open-redirect in a trusted API endpoint. - Compromised CDN or API gateway injecting redirects. - MITM on a plaintext hop in the redirect chain. ## Fix Add `COOKIE` to the headers removed alongside `AUTHORIZATION` / `PROXY_AUTHORIZATION` on the security-boundary branch: ```java if (stripAuthorization) { headers.remove(AUTHORIZATION) .remove(PROXY_AUTHORIZATION) .remove(COOKIE); } else if (realm != null && (realm.getScheme() == AuthScheme.NTLM || realm.getScheme() == AuthScheme.SCRAM_SHA_256)) { headers.remove(AUTHORIZATION) .remove(PROXY_AUTHORIZATION); } ``` Note that the URI-scoped `CookieStore` will re-add any cookies that legitimately match the new target after `propagatedHeaders` returns, so legitimate cross-origin sessions tracked by the client are not broken. Fixed in **3.0.10** and **2.15.0** by commit [`3b0e3e9e`](https://github.com/AsyncHttpClient/async-http-client/commit/3b0e3e9e).
Same vulnerability as
CVE-2026-45300 resolved according to EUVD-2026-34910
Analysis Read only

CVE is a trademark and the CVE logo is a registered trademark of The MITRE Corporation. CVE data may be incomplete, delayed, or inaccurate. This website and all information provided are offered on an “as is” basis without warranties of any kind. This site is not affiliated with, endorsed by, or sponsored by the CVE Program or The MITRE Corporation.

This site uses data from the National Vulnerability Database (NVD), obtained through Dependency-Track, but is not endorsed or certified by the NVD or the National Institute of Standards and Technology (NIST). NVD data may be incomplete, delayed, or inaccurate.

CVSS (Common Vulnerability Scoring System) is owned and managed by FIRST.Org, Inc. and used by permission. The links on CVSS vectors open the FIRST CVSS calculators (CVSS 3.0, 3.1 and 4.0), or the NVD calculator for CVSS 2.0. This site is not affiliated with, endorsed by, or sponsored by FIRST.

GitHub is a trademark of GitHub, Inc. GHSA identifiers and advisory data come from the GitHub Advisory Database, licensed under CC-BY 4.0. GHSA data may be incomplete, delayed, or inaccurate. This site is not affiliated with, endorsed by, or sponsored by GitHub, Inc.

Source of the EUVD data: European Vulnerability Database (EUVD), © European Union Agency for Cybersecurity (ENISA), reused with acknowledgement of the source as provided by the ENISA legal notice and IPR policy. Changes: CVEManager does not display the EUVD records as such; it uses their aliases to link the CVE and GHSA identifiers designating the same vulnerability. EUVD data may be incomplete, delayed, or inaccurate. This site is not affiliated with, endorsed by, or sponsored by ENISA or the European Union.