HTTP Library Flaw Lets Attackers Crash Your Server with One Request
Your application uses a popular tool called Axios to make web requests behind the scenes. A flaw in this tool means that if your app accepts any user-supplied data and passes it — even indirectly — into Axios, an attacker can send a single specially crafted message that instantly crashes your server. No password or account needed.
Business Impact And Actions
high urgencyBusiness Impact
If exploited, your application goes offline immediately and stays down until the server process is restarted. For customer-facing SaaS products, this means lost revenue, broken user sessions, and potential SLA breaches. Because the attack requires no login and can be repeated indefinitely, an attacker could keep your service down continuously. This may also trigger compliance flags if your product has uptime guarantees or handles sensitive data.
What To Do
- Ask your developer to check which version of Axios your project uses — run `npm list axios` in the project folder and share the output.
- If the version is below 0.30.3 (legacy branch) or below 1.13.5 (current branch), ask your developer to upgrade Axios immediately. This is a straightforward dependency update.
- Ask your developer to audit any API endpoints that accept JSON from users and pass it into outgoing HTTP request configuration — these are the specific code paths at risk.
- Consider adding a web application firewall (WAF) rule to block requests containing `__proto__` in JSON bodies as a short-term mitigation while the upgrade is being tested.
Axios < 0.30.3 / < 1.13.5 — Denial of Service via __proto__ Key in mergeConfig (CVE-2026-25639)
high severity CVSS 7.5Vulnerability Explanation
The `mergeConfig` function in `lib/core/mergeConfig.js` iterates over the merged keys of two config objects using `Object.keys({ ...config1, ...config2 })`. When a config object is created via `JSON.parse()` with a `__proto__` key (e.g., `JSON.parse('{"__proto__": {"x": 1}}')`), `JSON.parse` treats `__proto__` as a plain own enumerable property rather than a prototype accessor. `Object.keys()` then includes `'__proto__'` in the iteration. Inside the loop, `mergeMap['__proto__']` performs a prototype chain lookup and resolves to `Object.prototype` (a truthy non-function object). The expression `mergeMap[prop] || mergeDeepProperties` therefore evaluates to `Object.prototype`, which is then invoked as a function — throwing `TypeError: merge is not a function`. This unhandled exception crashes the Node.js process. The crash path is reachable through every public Axios method: `axios.get()`, `axios.post()`, `axios.request()`, `axios.getUri()`, and all other HTTP shortcut methods.
Root Cause
The `mergeConfig` function does not validate or filter dangerous prototype-related keys (`__proto__`, `constructor`, `prototype`) before using them as property lookups on `mergeMap`. Because `mergeMap` is a plain object, a lookup for `__proto__` traverses the prototype chain and returns `Object.prototype` instead of `undefined`, producing a truthy non-function value that is subsequently called as a function.
Technical Impact
Remote, unauthenticated denial of service. An attacker who can influence any JSON input that flows into an Axios config object can crash the Node.js process with a single HTTP request. No data is read or written — availability is the sole impact. The attack can be repeated to prevent service recovery.
Severity Justification
CVSS 3.1 AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H — network-reachable, no authentication required, no user interaction, complete availability impact. Exploitability is conditional on the application passing user-controlled JSON into Axios config, which is a common pattern.
Affected Components
axios < 0.30.3 (0.x legacy branch)axios >= 1.0.0 < 1.13.5 (1.x current branch)
Remediation Steps
- Upgrade Axios to the patched version for your branch: `npm install axios@latest` (1.x) or `npm install axios@0.30.3` (0.x legacy). Run `npm list axios` afterwards to confirm the resolved version.
- If you cannot upgrade immediately, add input sanitization before passing any user-supplied JSON to Axios config: strip or reject objects containing `__proto__`, `constructor`, or `prototype` as own keys.
- Wrap Axios calls that process user-controlled config in a try/catch block as a short-term resilience measure — this prevents a single bad request from crashing the entire process, though it does not fix the root cause.
- After upgrading, audit all code paths where `JSON.parse()` output (or any user-supplied object) is spread or passed directly into an Axios request config parameter.
- Run `npm audit` to confirm no remaining advisories for Axios and to check for transitive dependencies that may pin an older version.
Verification Steps
- Run `npm list axios` and confirm the resolved version is >= 1.13.5 (or >= 0.30.3 for the 0.x branch).
- Run `npm audit` and verify no CVE-2026-25639 findings are reported.
- In a non-production environment, execute the PoC: `node -e "import('axios').then(({default: axios}) => axios.get('http://localhost', JSON.parse('{\"__proto__\": {\"x\": 1}}')))"` — on a patched version this should throw a network error (not a TypeError crash).
- Check your CI pipeline's dependency lock file (`package-lock.json` or `yarn.lock`) to ensure no nested dependency is resolving an older Axios version.
Code Examples (javascript)
// Vulnerable: user-controlled JSON passed directly to axios config
app.post('/proxy', async (req, res) => {
const userConfig = JSON.parse(req.body.config); // attacker controls this
const response = await axios.get('https://api.example.com/data', userConfig);
// ^ crashes with TypeError if userConfig contains __proto__
res.json(response.data);
});
// Fixed option 1: upgrade to axios >= 1.13.5 (primary fix)
// Fixed option 2: sanitize config before passing to axios
const DANGEROUS_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
function sanitizeConfig(obj) {
if (obj === null || typeof obj !== 'object') return obj;
return Object.fromEntries(
Object.entries(obj)
.filter(([key]) => !DANGEROUS_KEYS.has(key))
.map(([key, val]) => [key, sanitizeConfig(val)])
);
}
app.post('/proxy', async (req, res) => {
const rawConfig = JSON.parse(req.body.config);
const safeConfig = sanitizeConfig(rawConfig); // belt-and-suspenders
const response = await axios.get('https://api.example.com/data', safeConfig);
res.json(response.data);
});
Best Practices
- Never pass raw `JSON.parse()` output directly into library configuration objects — always validate or allowlist the expected fields.
- Use `Object.create(null)` for lookup maps (like `mergeMap`) to avoid prototype chain pollution; plain `{}` objects inherit from `Object.prototype`.
- Add `npm audit` or a software composition analysis (SCA) tool to your CI pipeline to catch vulnerable dependency versions before they reach production.
- Wrap external HTTP client calls in try/catch blocks so that unexpected runtime errors degrade gracefully rather than crashing the process.
Found this in your infrastructure?
VulWall scans for this and dozens of other issues automatically.
Scan Your Domain Free