CVE
CVE-2026-67320
CWE
CWE-200
Affected Surface
- The npm package `axios` in versions `>= 0.31.1` and `< 0.33.0`
- The npm package `axios` in versions `>= 1.15.2` and `< 1.18.0`
- Node.js services using the HTTP adapter, including default server-side axios usage
- Applications whose request interceptors clone config objects with patterns such as `{...config}` or `Object.assign({}, config)`
- Processes already exposed to prototype pollution through another dependency, parser, or upstream bug
CVE-2026-67320 is not another generic “prototype pollution somewhere in JavaScript” warning. The interesting part is that axios had already added hardening specifically meant to keep polluted Object.prototype values out of request config. The bug is that an ordinary immutable request interceptor can undo that hardening by cloning the config back into a normal object before dispatch.
Once that happens, the Node HTTP adapter can read config.proxy through the prototype chain again. If another vulnerable component in the same process has already polluted Object.prototype.proxy, axios can silently route the outgoing request through an attacker-controlled proxy.
Affected package and versions
Affected npm package:
axios>= 0.31.1and< 0.33.0axios>= 1.15.2and< 1.18.0
Patched versions:
axios0.33.0axios1.18.0
This issue is limited to Node.js request paths that use axios’s HTTP adapter. The disclosure does not establish browser impact, and it does not establish HTTPS header or body disclosure under normal TLS validation. The highest-confidence impact is plaintext HTTP traffic in Node.js services.
That caveat matters, but it does not make the bug unimportant. Many internal services, CI helpers, webhooks, metadata fetchers, and service-to-service clients still use plaintext HTTP on local networks, sidecar links, or development infrastructure.
The exact hardening failure
Axios’s intended defense is sound in principle. During config merging, it creates a null-prototype object so inherited values from Object.prototype are not consulted:
const config = Object.create(null);
The problem is what happens next. Request interceptors run after that merge, and axios lets the interceptor return a replacement config object. A very common pattern looks like this:
api.interceptors.request.use((config) => ({
...config,
headers: {
...config.headers,
'X-App': 'demo'
}
}));
That code is not obviously dangerous. It is the kind of immutable config transformation many teams prefer in production code. But {...config} turns the hardened null-prototype config back into a regular object whose prototype is Object.prototype.
Axios then dispatches that replacement object without re-hardening it.
Why the Node adapter becomes the sink
The important code-level sequence described in the advisory is:
mergeConfig()
-> creates null-prototype config
request interceptor
-> returns plain object clone
dispatchRequest()
-> forwards cloned config without re-hardening
http adapter
-> reads config.proxy
-> inherited Object.prototype.proxy is now visible
The vulnerable adapter behavior is conceptually simple:
setProxy(
options,
config.proxy,
protocol + '//' + parsed.hostname + (parsed.port ? ':' + parsed.port : '') + options.path
);
If config.proxy is not an own property anymore, that read can resolve to attacker-controlled prototype data.
What a real exploit chain looks like
The attack is not “axios alone gives remote code execution.” The realistic exploit chain is two-stage:
- some other package or parser bug in the process pollutes
Object.prototype.proxy - axios later re-exposes that property by cloning hardened config into a regular object
The polluted value can look like:
Object.prototype.proxy = {
protocol: 'http',
host: '127.0.0.1',
port: 8080
};
With the interceptor pattern above in place, affected axios requests can be sent to the attacker’s proxy instead of the intended target.
Confirmed impact
The public proof of concept shows more than just redirection. For plaintext HTTP requests, the attacker-controlled proxy can observe:
- explicit
Authorizationheaders - axios-generated Basic auth derived from
config.auth - request method
- absolute URL
Hostheader- request body
The proxy can also return its own response body to axios, so the client thinks the target server responded when the proxy actually did.
Representative vulnerable output from the disclosure shows:
{
"explicitResponse": {"server": "proxy"},
"basicResponse": {"server": "proxy"},
"postResponse": {"server": "proxy"},
"targetHits": [],
"proxyHits": [
{
"url": "http://127.0.0.1:40613/api/secret",
"method": "POST",
"authorization": "Bearer EXPLICIT_SECRET",
"host": "127.0.0.1:40613",
"body": "{\"secret\":\"request-body-secret\"}"
}
],
"finalConfigPrototype": "Object.prototype",
"finalConfigHasOwnProxy": false
}
That result is exactly why the issue deserves its own article. The harmful transition is not abstract prototype pollution. It is a documented hardening boundary being undone by ordinary interceptor code.
When you are and are not exposed
The highest-risk conditions are:
- Node.js runtime
- axios HTTP adapter path
- a request interceptor that returns a plain object clone
- prior prototype pollution elsewhere in the process
- no explicit own
proxy: falseor other safe ownproxyvalue
Conditions that reduce or remove exposure include:
- browser adapters
- the fetch adapter in Node.js
- returning the original hardened config object instead of a clone
- cloning into a null-prototype object
- an own
proxy: falseon the instance or request
But those are mitigations, not substitutes for patching. The affected versions should still be upgraded because teams rarely control every library in-process well enough to guarantee “no prototype pollution can ever happen first.”
Real-world places this matters
This is not limited to hand-written REST clients. The pattern shows up in:
- API gateway and BFF services that add headers in interceptors
- internal SDK wrappers that standardize auth and tracing metadata
- webhook relays and service connectors that fetch attacker-influenced URLs
- CI and deployment helpers that call internal HTTP services with bearer tokens
- metadata harvesters and background jobs that still use plaintext HTTP on trusted networks
Those services often carry secrets that are far more valuable than the application payload itself.
Detection and scoping
Start with version inventory:
npm ls axios
pnpm why axios
yarn why axios
Then search for the risky adapter and interceptor patterns:
rg -n "interceptors\\.request\\.use|Object\\.assign\\(\\{\\}, config\\)|\\.\\.\\.config|adapter:\\s*['\"]http['\"]|proxy:\\s*false" src app lib packages scripts
The most important code review question is:
Can this process suffer prototype pollution from some other input path,
and do our axios interceptors return plain object clones?
If both answers are yes, vulnerable axios versions turn that combination into a request-redirection problem.
Remediation
Upgrade to a fixed version:
npm install axios@^1.18.0
# or, on the 0.x line:
npm install axios@^0.33.0
Then verify the resolved tree:
npm ls axios
If you cannot patch immediately, temporary risk reduction steps include:
- set an own
proxy: falsewhere proxy support is not needed - avoid interceptors that clone config into ordinary objects
- prefer returning the original config object or a null-prototype clone
- use the fetch adapter where behavior is compatible and reviewed
Those steps reduce exposure, but they are brittle. The real fix is the patched axios release that restores the intended hardening guarantees.
Response guidance
If a service used vulnerable axios versions on the Node HTTP adapter and also had a reachable prototype-pollution path:
- review plaintext HTTP requests made during the exposure window
- rotate credentials that may have been present in axios headers or
config.auth - inspect outbound traffic for unexpected proxy routing
- review interceptor code that clones config objects
The deeper AppSec lesson is valuable beyond axios. Security controls implemented at “merge time” can be lost if later extension points rebuild objects without preserving the same invariants. In this case, the invariant was “config reads must not consult Object.prototype.” CVE-2026-67320 shows how one common {...config} pattern was enough to break it.
From research to remediation
Check whether this pattern exists in your codebase
Turn this research into a remediation workflow. Scan dependencies and package manifests for similar supply-chain risk, then prioritize fixes with reachability context.