GHSA-j5f8-grm9-p9fc: Axios: Proxy-Authorization header leaks to redirect target when proxy is re-evaluated to direct connection
SummaryAxios’ Node.js HTTP adapter can leak proxy credentials to a redirect target in affected versions. When a request is sent through an authenticated proxy, Axios may add a `Proxy-Authorization` header. If Axios then follows a redirect and the redirected request is no longer sent through that proxy, the stale `Proxy-Authorization` header can remain on the redirected request and be sent to the redirect target.This affects Node.js's use of Axios with automatic redirects enabled and an authenticated proxy configuration. Browser adapters are not affected.ImpactAn attacker who controls a server that the victim application requests can redirect the request so that the attacker-controlled redirect target receives the victim’s proxy credentials.The most relevant case is a Node.js application using an authenticated `HTTP_PROXY` for an initial `http://` request, with redirects enabled, where the redirect target resolves to no proxy, such as an `https://` URL when `HTTPS_PROXY` is unset.This does not affect browser, XHR, or fetch adapter behaviour. It also does not affect requests with `maxRedirects: 0`.Affected FunctionalityAffected functionality is limited to the Node.js HTTP adapter in `lib/adapters/http.js`.Relevant inputs and settings include:`HTTP_PROXY`, `HTTPS_PROXY`, and `NO_PROXY`.Authenticated proxy URLs such as `http://user:pass@proxy.example:8080`.Automatic redirect following through `follow-redirects`.Axios proxy handling in `setProxy()`.Redirect proxy handling through `beforeRedirects.proxy`.Technical DetailsIn affected v1 releases, `setProxy()` adds `Proxy-Authorization` when a proxy with credentials is selected, but redirect handling calls `setProxy()` again without first clearing any existing proxy authorization header.If the redirected URL resolves to no proxy, `setProxy()` does not add a new proxy configuration and also does not remove the old header. The redirected request can therefore carry the stale `Proxy-Authorization` header to the final origin.The v1 fix in `afca61a` adds an `isRedirect` path that deletes any case variant of `Proxy-Authorization` before proxy settings are re-applied on redirect. The v0 backport in `2af6116` fixed the 0.x line for `0.32.0`.Proof of Concept of AttackAttacker-controlled HTTP endpoint:Expected result on affected versions:Expected result on fixed versions:WorkaroundsSet `maxRedirects: 0` and handle redirects manually.Avoid using authenticated proxy environment variables for requests to untrusted HTTP origins unless redirect behaviour is controlled.Ensure proxy environment variables are configured consistently across protocols so redirects do not unexpectedly change from proxied to direct connections.SummaryAxios' Node.js HTTP adapter can leak proxy credentials to a redirect target origin. When an initial request is sent through an authenticated HTTP proxy, Axios adds a `Proxy-Authorization` header. On redirect, Axios re-evaluates proxy settings, but if the redirected request no longer uses a proxy, the stale `Proxy-Authorization` header is not cleared. As a result, the redirect target can receive the proxy credential directly.This issue affects the Node.js HTTP adapter and can be reproduced when the initial request uses `HTTP_PROXY` with authentication, redirects are enabled, and the redirected request is resolved to no proxy, such as when `HTTPS_PROXY` is unset or the redirect target is excluded by `NO_PROXY`.DetailsIn the current implementation:`setProxy()` adds `Proxy-Authorization` when a proxy with credentials is in use.On redirects, Axios re-invokes `setProxy()` for the redirected request.If the redirected URL re-evaluates to "no proxy", `setProxy()` does not clear the previously added `Proxy-Authorization` header.The redirected request therefore reuses the stale header and sends it to the final origin.Relevant code locations:`lib/adapters/http.js``setProxy()` adds `Proxy-Authorization`redirect handling re-applies proxy logic through `beforeRedirects.proxy`no cleanup is performed when the recomputed redirect request no longer uses a proxyPoCThe victim sends `GET http://<attacker-site>/start`The request goes through a local authenticated `corp proxy`The attacker-controlled HTTP endpoint returns `302 Location: https://<attacker-site>/final`The redirected HTTPS request no longer uses a proxyThe attacker-controlled HTTPS endpoint receives the stale `Proxy-Authorization` headerObserved output:This demonstrates that the proxy credential is exposed to the redirect target origin.ImpactExposes authenticated proxy credentials to an attacker-controlled origin.
CVSS v3.1: 7.5