# Axios: Header Injection via Prototype Pollution

Prototype pollution gadget in Axios's HTTP adapter makes plain object payloads pass FormData duck-typing, letting attacker-controlled getHeaders() inject arbitrary headers into outgoing requests.

- Payout: Research
- Severity: high
- Program: Axios
- Found by: raulvdv
- Disclosed: 2026-05-05
- CVE: CVE-2026-42035
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-6chq-wfr3-2hj9
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-6chq-wfr3-2hj9
- Tags: area:oss domain:oss impact:integrity impact:privesc kind:research platform:ghsa sev:high tech:nodejs technique:source-review vuln:auth-bypass vuln:crlf-injection vuln:prototype-pollution

**Target:** npm axios HTTP adapter (lib/adapters/http.js) data serialization
**Root cause:** Axios duck-types FormData via isFormData plus isFunction(data.getHeaders) without an own-property check, so polluted Object.prototype members satisfy the checks and attacker getHeaders() output is merged into request headers.
**Steps:**
1. Pollute Object.prototype with `Symbol.toStringTag='FormData'`, `append`, `getHeaders`, `pipe`, `on`, `once` functions.
2. Have application call `axios.post(url, {userId:42}, {headers:{Authorization:'Bearer VALID_USER_TOKEN'}})` with a plain object payload.
3. Axios's isFormData returns true via polluted toStringTag/append, and isFunction(data.getHeaders) is true from prototype.
4. Axios calls the attacker getHeaders() and merges returned headers into the outgoing request.
**How found:** Code reading of the data serialization pipeline in lib/adapters/http.js, noticing the FormData duck-type check relies on inherited prototype properties rather than own properties.
**Exploitation:** Any prototype pollution primitive in the dependency tree (lodash.merge, qs, JSON5) sets Object.prototype.getHeaders to return arbitrary headers; subsequent Axios POST/PUT/PATCH with a plain object payload sends those injected headers (e.g. X-User-ID, Authorization) to downstream services that trust gateway-forwarded identity headers.
**Escalation:** In service-to-service architectures, injected identity headers cross a trust boundary into downstream services, enabling auth bypass, privilege escalation, and IP spoofing/WAF bypass (argued S:C, CVSS 10.0).
**Insight:** Duck-typing checks that read methods off an object (isFormData + isFunction(data.getHeaders)) are prototype-pollution gadgets; audit libraries for type checks that don't use hasOwnProperty, since any pollution primitive anywhere in the dependency tree can weaponize them.

## Proof of concept (copied exactly from the original report)

**Prototype pollution PoC injecting headers via axios.post**

```
// Simulate Prototype Pollution
Object.prototype[Symbol.toStringTag] = 'FormData';
Object.prototype.append = () => {};
Object.prototype.getHeaders = () => {
    const headers = Object.create(null);
    (.... Introduce here all the headers you want ....)
    return headers;
};
Object.prototype.pipe = function(d) { if(d&&d.end)d.end(); return d; };
Object.prototype.on = function() { return this; };
Object.prototype.once = function() { return this; };

// Legitimate application code
const response = await axios.post('https://internal-api.company.com/admin/delete', 
    { userId: 42 },
    { headers: { 'Authorization': 'Bearer VALID_USER_TOKEN' } }
);
```

