GHSA-3w6x-2g7m-8v23 Axios: Invisible JSON Response Tampering via Prototype Pollution Gadget in `parseReviver`
Vulnerability Disclosure: Invisible JSON Response Tampering via Prototype Pollution Gadget in `parseReviver`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 **surgical, invisible modification of all JSON API responses** — including privilege escalation, balance manipulation, and authorization bypass.The 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.This is **strictly more powerful** than the `transformResponse` gadget because:**No constraints** — the reviver can return any value (no "must return true" requirement)**Selective modification** — individual JSON keys can be changed while others remain untouched**Invisible** — the response structure and most values look completely normal**Simultaneous exfiltration** — the reviver sees the original values before modification**Severity:** Critical (CVSS 9.1)
**Affected Versions:** All versions (v0.x - v1.x including v1.15.0)
**Vulnerable Component:** `lib/defaults/index.js:124` (JSON.parse with prototype-inherited reviver)CWE**CWE-1321:** Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')**CWE-915:** Improperly Controlled Modification of Dynamically-Determined Object AttributesCVSS 3.1**Score: 9.1 (Critical)**Vector: `CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N`| Metric | Value | Justification |
|---|---|---|
| Attack Vector | Network | PP is triggered remotely via any vulnerable dependency |
| Attack Complexity | Low | Once PP exists, single property assignment. Consistent with GHSA-fvcv-3m26-pcqx scoring methodology |
| Privileges Required | None | No authentication needed |
| User Interaction | None | No user interaction required |
| Scope | Unchanged | Within the application process |
| 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 |
| 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 |
| Availability | None | No crash, no error — the attack is entirely silent |Comparison with All Known Axios PP Gadgets| Factor | GHSA-fvcv-3m26-pcqx (Header Injection) | transformResponse | proxy (MITM) | **parseReviver (This)** |
|---|---|---|---|---|
| PP target | `Object.prototype['header']` | `Object.prototype.transformResponse` | `Object.prototype.proxy` | `Object.prototype.parseReviver` |
| Fixed by 1.15.0? | Yes | No | No | **No** |
| Constraints | N/A (fixed) | **Must return `true`** | None | **None** |
| Data modification | Header injection only | Response replaced with `true` | Full MITM | **Selective per-key modification** |
| Stealth | Request anomaly visible | Response becomes `true` (obvious) | Proxy visible in network | **Completely invisible** |
| Data access | Headers only | `this.auth` + raw response | All traffic | **Every JSON key-value pair** |
| Validated? | N/A | `assertOptions` validates | Not validated | **Not validated** |
| In defaults? | N/A | Yes → goes through mergeConfig | No → bypasses mergeConfig | **No → bypasses mergeConfig** |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`), 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.Root Cause AnalysisThe Attack PathWhy `parseReviver` Bypasses ALL Existing Protections**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.**Not in assertOptions schema** (`lib/core/Axios.js:135-142`): The schema only contains `{baseUrl, withXsrfToken}`. `parseReviver` is not validated.**No type check**: The `JSON.parse` API accepts any function as a reviver. There is no check that `this.parseReviver` is intentionally set.**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.Vulnerable Code**File:** `lib/defaults/index.js`, line 124Proof of ConceptVerified PoC OutputImpact Analysis1. Authorization / Privilege Escalation2. Financial Manipulation3. Security Control Bypass4. Silent Data ExfiltrationThe 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.5. Universal and InvisibleAffects **every** Axios request that receives a JSON responseThe response structure is intact — only specific values are changedNo errors, no crashes, no suspicious behaviorApplication logs show normal-looking API responses with tampered valuesRecommended FixFix 1: Use `hasOwnProperty` check before using `parseReviver`Fix 2: Use null-prototype config objectFix 3: Validate `parseReviver` type and sourceRelationship to Other Reported GadgetsThis vulnerability shares the same **root cause class** — unsafe prototype chain traversal on the merged config object — with two other reported gadgets:| Report | PP Target | Code Location | Fix Location | Impact |
|---|---|---|---|---|
| axios_26 | `transformResponse` | `mergeConfig.js:49` (defaultToConfig2) | `mergeConfig.js` | Credential theft, response replaced with `true` |
| axios_30 | `proxy` | `http.js:670` (direct property access) | `http.js` | Full MITM, traffic interception |
| **axios_31 (this)** | `parseReviver` | `defaults/index.js:124` (this.parseReviver) | `defaults/index.js` | **Selective JSON value tampering + data exfiltration** |Why These Are Distinct Vulnerabilities**Different polluted properties:** Each targets a different `Object.prototype` key.**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.**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.**Different impact profiles:** `transformResponse` is constrained to return `true`; `proxy` requires a proxy server; `parseReviver` enables constraint-free selective value modification.Comprehensive FixWhile 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.Resources[CWE-1321: Prototype Pollution](https://cwe.mitre.org/data/definitions/1321.html)[CWE-915: Improperly Controlled Modification of Dynamically-Determined Object Attributes](https://cwe.mitre.org/data/definitions/915.html)[GHSA-fvcv-3m26-pcqx: Related PP Gadget in Axios (Fixed in 1.15.0)](https://github.com/advisories/GHSA-fvcv-3m26-pcqx)[MDN: JSON.parse reviver](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse#the_reviver_parameter)[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 — selective response tampering confirmed |
| TBD | Report submitted to vendor via GitHub Security Advisory |
CVSS v3.1 score: 6.5