Listen to this Post
Intro
CVE-2018-16487 is a prototype pollution vulnerability in `lodash.merge` versions ≤4.17.10. An attacker who controls a shallow or deep merge operation can inject arbitrary properties into Object.prototype. When an application uses such a polluted `lodash` function (or any other upstream gadget) and then later loads `axios` version 1.15.2 in the same Node.js process, `axios` silently picks up the polluted values due to two read‑side gadgets.
First, in `lib/utils.js` line 406, the `merge()` helper creates a plain object result = {}. When iterating over keys, line 414 reads result
</code>. If `targetKey` matches a polluted slot (e.g., <code>common</code>, <code>get</code>, <code>post</code>), the prototype chain is walked, returning the attacker‑controlled nested object. That object’s own keys are then copied into headers via recursive merge, finally reaching the HTTP wire.
Second, in `lib/core/mergeConfig.js` line 26, a descriptor literal `{ get: undefined, set: undefined, ... }` is built. The `get` and `set` lookups traverse <code>Object.prototype</code>. If an attacker polluted `Object.prototype.get` or `Object.prototype.set` with a non‑function value, `Object.defineProperty` throws `TypeError: Getter must be a function` (or <code>Setter</code>). This crash happens synchronously on every axios request (GET, POST, etc.) because `mergeConfig` is called unconditionally.
No per‑request header overwrite protects against the crash gadget, and the header injection works for any method unless the application explicitly provides its own header that overwrites the polluted slot. The attack flow requires a prior prototype pollution (e.g., via `lodash.merge` with CVE‑2018‑16487) and then any axios request.
<h2 style="color: blue;">DailyCVE Form:</h2>
Platform: Node.js
Version: axios 1.15.2
Vulnerability: Prototype pollution
Severity: Critical
date: 2026-05-29
<h2 style="color: blue;">Prediction: 2026-06-15</h2>
<h2 style="color: blue;">What Undercode Say:</h2>
Analytics – run these commands to reproduce and detect:
[bash]
Install vulnerable versions
npm install [email protected] [email protected]
Reproduce header injection (Finding A)
node -e "const axios = require('axios'); Object.prototype.common = { 'X-Poisoned': 'yes' }; axios.get('http://api.example.com/users').catch(e=>console.log(e))"
Reproduce crash DoS (Finding B)
node -e "const axios = require('axios'); Object.prototype.get = {}; axios.get('http://api.example.com/users').catch(e=>console.log(e))"
Check for polluted prototype in running process
node -e "console.log(Object.prototype.common, Object.prototype.get)"
Exploit:
- Header injection: Pollute `Object.prototype.common` → every request carries injected headers (e.g., `Content-Length: 99999` causing hang, `Transfer-Encoding: chunked` causing 400, `If-None-Match: ` causing 304).
- Crash DoS: Pollute `Object.prototype.get` or `.set` with any non‑function → all axios requests throw synchronous
TypeError; not anAxiosError, so filters like `error.isAxiosError` fail.
Protection:
- Upgrade axios to ≥1.16.0 (if available) or patch manually: replace `{}` with `Object.create(null)` in `lib/utils.js:406` and
lib/core/mergeConfig.js:26-31. - Use `Object.freeze(Object.prototype)` or runtime prototype pollution prevention (e.g., `--disable-proto=delete` in Node.js).
- Avoid merging user input with vulnerable
lodash.merge; use `lodash.mergeWith` with a customizer that rejects__proto__,constructor, etc.
Impact:
- Server hang / CL‑TE confusion leading to DoS.
- Response suppression (304) for GET/HEAD requests.
- Complete denial of service (crash) for all HTTP requests made by axios, breaking the entire application.
🎯Let’s Practice Exploiting & Learn Patching For Free:
Sources:
Reported By: github.com
Extra Source Hub:
Undercode
🎓 Live Courses & Certifications:
Join Undercode Academy for Verified Certifications
🚀 Request a Custom Project:
Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]

