GHSA-35jp-ww65-95wh: axios Vulnerable to Full Man-in-the-Middle via Prototype Pollution Gadget in `config.proxy`
Vulnerability Disclosure: Full Man-in-the-Middle via Prototype Pollution Gadget in `config.proxy`SummaryThe Axios library is vulnerable to a Prototype Pollution "Gadget" attack that allows any `Object.prototype` pollution in the application's dependency tree to be escalated into a **full Man-in-the-Middle (MITM) attack** — intercepting, reading, and modifying all HTTP traffic including authentication credentials.The HTTP adapter at `lib/adapters/http.js:670` reads `config.proxy` via standard property access, which traverses the prototype chain. Because `proxy` is **not present in Axios defaults**, the merged config object has no own `proxy` property, making it trivially injectable via prototype pollution. Once injected, `setProxy()` routes **all** HTTP requests through the attacker's proxy server.Unlike the `transformResponse` gadget (which is constrained by `assertOptions` to return `true`), the proxy gadget has **zero constraints** — the attacker gets a full MITM position with the ability to read all credentials and tamper with all responses.**Severity:** Critical (CVSS 9.4)
**Affected Versions:** All versions (v0.x - v1.x including v1.15.0)
**Vulnerable Component:** `lib/adapters/http.js` (config property access on merged object)CWE**CWE-1321:** Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')**CWE-441:** Unintended Proxy or Intermediary ('Confused Deputy')CVSS 3.1**Score: 9.4 (Critical)**Vector: `CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:L`| Metric | Value | Justification |
|---|---|---|
| Attack Vector | Network | PP is triggered remotely via any vulnerable dependency |
| Attack Complexity | Low | Once PP exists, single property assignment: `Object.prototype.proxy = {host:'attacker', port:8080}`. Consistent with GHSA-fvcv-3m26-pcqx scoring methodology |
| Privileges Required | None | No authentication needed |
| User Interaction | None | No user interaction required |
| Scope | Unchanged | MITM within the application's network context |
| Confidentiality | **High** | Attacker sees ALL request data: Authorization headers, auth credentials, cookies, request bodies, full URLs (including internal hostnames) |
| Integrity | **High** | Attacker can modify ALL responses: inject malicious data, alter API results, redirect authentication flows. **No constraints** — unlike `transformResponse` which must return `true` |
| Availability | Low | Attacker could drop requests or return errors, but this is secondary to C/I impact |Why This Bypasses mergeConfigThe critical difference from `transformResponse`: the `proxy` property is **not in defaults** (`lib/defaults/index.js` does not set `proxy`). This means:`mergeConfig` iterates `Object.keys({...defaults, ...userConfig})` — `proxy` is NOT in this set`defaultToConfig2` for `proxy` is never calledThe merged config has **no own `proxy` property**When `http.js:670` reads `config.proxy`, JavaScript traverses the prototype chain`Object.prototype.proxy` is found → used by `setProxy()`This is a **more direct attack path** than `transformResponse` because it doesn't even go through `mergeConfig`'s merge logic — it completely bypasses it.Usage of "Helper" VulnerabilitiesThis vulnerability requires **Zero Direct User Input**.If an attacker can pollute `Object.prototype` via any other library in the stack (e.g., `qs`, `minimist`, `lodash`, `body-parser`), Axios will automatically use the polluted `proxy` value when making HTTP requests. The developer's code is completely safe — no configuration errors needed.Proof of Concept1. The Setup (Simulated Pollution)Imagine a scenario where a known prototype pollution vulnerability exists in a query parser. The attacker sends a payload that sets:2. The Gadget Trigger (Safe Code)The application makes a completely safe, hardcoded request:3. The ExecutionAt `http.js:668-670`:`setProxy()` at `http.js:191-239` then:4. The Impact (Full MITM)The attacker's proxy server receives:The `Authorization` header contains `svc-account:prod-key-abc123!` in Base64. The attacker:**Sees** every request URL, header, and body**Modifies** every response (inject malicious data, change auth results)**Logs** all API keys, session tokens, and passwordsOperates as an **invisible** proxy — the developer has no indication5. Verified PoC CodeVerified PoC OutputImpact Analysis**Full Credential Interception:** Every HTTP request's `Authorization` header, cookies, API keys, and request bodies are visible to the attacker's proxy in plaintext.**Arbitrary Response Tampering:** The attacker can return any response data — no constraints like `transformResponse`'s "must return true".**Internal Network Reconnaissance:** The proxy sees all request URLs, revealing internal hostnames, ports, and API paths.**Universal Scope:** Affects every axios HTTP request in the application, including all third-party libraries that use axios.**Invisible Attack:** The developer has no indication that a proxy has been injected — requests complete normally with attacker-controlled responses.**Bypass of 1.15.0 Fix:** The header sanitization patch in v1.15.0 (GHSA-fvcv-3m26-pcqx) does NOT address this vector.Why This Is More Severe Than transformResponse (axios_26)| Dimension | transformResponse Gadget | **proxy Gadget** |
|---|---|---|
| Data access | `this.auth` + response data | **All headers, auth, body, URL, response** |
| Response control | Must return `true` | **Arbitrary responses** |
| Attack visibility | Response becomes `true` (suspicious) | **Normal-looking responses (invisible)** |
| mergeConfig involvement | Goes through defaultToConfig2 | **Bypasses mergeConfig entirely** |Recommended FixFix 1: Use `hasOwnProperty` when reading security-sensitive config propertiesFix 2: Enumerate all properties not in defaults and apply `hasOwnProperty`Properties not in defaults that are read by http.js and have security impact:`config.proxy` — MITM`config.socketPath` — Unix socket SSRF`config.transport` — request hijack`config.lookup` — DNS hijack`config.beforeRedirect` — redirect manipulation`config.httpAgent` / `config.httpsAgent` — agent injectionAll should use `hasOwnProperty` checks.Fix 3: Use null-prototype object for merged configResources[CWE-1321: Prototype Pollution](https://cwe.mitre.org/data/definitions/1321.html)[CWE-441: Unintended Proxy](https://cwe.mitre.org/data/definitions/441.html)[GHSA-fvcv-3m26-pcqx: Related PP Gadget in Axios (Fixed in 1.15.0)](https://github.com/advisories/GHSA-fvcv-3m26-pcqx)[Axios GitHub Repository](https://github.com/axios/axios)Timeline| Date | Event |
|---|---|
| 2026-04-16 | Vulnerability discovered during source code audit |
| 2026-04-16 | PoC developed and verified — full MITM confirmed |
| TBD | Report submitted to vendor via GitHub Security Advisory |
CVSS v3.1: 8.7