CVE-2026-44490: Axios Denial of Service Vulnerability
MODERATECVE-2026-44490 is a MODERATE (CVSS 4.8) denial of service vulnerability (CWE-1321: Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')) affecting Axios libraries in the npm ecosystem. The issue involves axios has dos & header injection via prototype pollution read-side gadgets in axios merge functions. Remediation is available by upgrading affected packages to version 1.16.0, 0.32.0.
CVE-2026-44490 at a Glance
Security Impact
CVSS: 4.8
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:N/I:L/A:L).
How to Fix CVE-2026-44490
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.16.0
npm install axios@0.32.0
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-44490, 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.16.0), 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-44490 Affected Axios Versions
2 component(s)References
Frequently Asked Questions
What is CVE-2026-44490?
Which Axios versions are affected?
What version fixes CVE-2026-44490?
Is axios affected?
What is the CVSS score of CVE-2026-44490?
What CWE is associated with CVE-2026-44490?
How can I check npm dependencies for CVE-2026-44490?
Machine-readable OSV JSON
OSV v1.5 Schema
{
"schema_version" : "1.4.0",
"id" : "GHSA-898c-q2cr-xwhg",
"modified" : "2026-06-12T19:25:04Z",
"published" : "2026-05-29T15:54:57Z",
"aliases" : [ "CVE-2026-44490" ],
"summary" : "axios has DoS & Header Injection via Prototype Pollution Read-Side Gadgets in axios merge functions",
"details" : "## Summary\n\naxios `1.15.2` exposes two read-side prototype-pollution gadgets. When `Object.prototype` is polluted by an upstream dependency in the same process (e.g. lodash `_.merge` / [CVE-2018-16487](https://nvd.nist.gov/vuln/detail/CVE-2018-16487)), axios silently picks up the polluted values:\n\n1. **Header injection** - `lib/utils.js` line 406 builds `merge()`'s accumulator as `result = {}`, so `result[targetKey]` (line 414) walks `Object.prototype` and the polluted bucket's own keys are copied into the merged headers and ride out on the wire.\n2. **Crash DoS** - `lib/core/mergeConfig.js` line 26 builds the `hasOwnProperty` descriptor as a plain-object literal. `Object.defineProperty` reads `descriptor.get`/`descriptor.set` via the prototype chain, so a polluted `Object.prototype.get` or `Object.prototype.set` makes the call throw `TypeError` synchronously on every axios request.\n\n## Affected Properties\n\n| Polluted slot | Effect |\n|---|---|\n| `Object.prototype.common` | injects headers on every method |\n| `Object.prototype.delete` / `.head` / `.post` / `.put` / `.patch` / `.query` | injects headers on the matching method |\n| `Object.prototype.get` | every axios request throws `TypeError: Getter must be a function` from `mergeConfig.js:26` |\n| `Object.prototype.set` | every axios request throws `TypeError: Setter must be a function` from `mergeConfig.js:26` |\n\nPer-request headers (`axios.request(url, { headers: {...} })`) overwrite polluted entries. Polluting `Object.prototype.get` triggers the crash before any header is built.\n\n## Proof of Concept\n\n```javascript\nconst axios = require('axios');\n\n// Finding A - header injection\nObject.prototype.common = { 'X-Poisoned': 'yes' };\nawait axios.get('http://api.example.com/users');\n// Wire request carries `X-Poisoned: yes`.\n\n// Finding B - crash DoS\nObject.prototype.get = { something: 'anything' };\nawait axios.get('http://api.example.com/users');\n// TypeError: Getter must be a function: #<Object>\n// at Function.defineProperty (<anonymous>)\n// at mergeConfig (lib/core/mergeConfig.js:26:10)\n```\n\n## Impact\n\n- **Server hang** (`Content-Length: 99999`): receiver waits for a body that never arrives. Affects requests with a body.\n- **CL+TE conflict** (`Transfer-Encoding: chunked` rides alongside axios's auto `Content-Length`): receiver rejects with `400 Bad Request`. Affects requests with a body.\n- **Response suppression** (`If-None-Match: *`): receiver returns empty `304 Not Modified`. Affects GET / HEAD.\n- **Crash DoS** (`Object.prototype.get` / `.set`): every axios request fails synchronously with `TypeError`, not `AxiosError`, so handlers filtering on `error.isAxiosError` mishandle the failure.\n\n## Attack Flow\n\n```mermaid\nflowchart TD\n ROOT[\"Polluted Object.prototype<br/>via upstream gadget (e.g. lodash <= 4.17.10 _.merge / CVE-2018-16487)<br/>axios <= 1.15.2\"]\n\n ROOT --> CLASS_A[\"A. Arbitrary HTTP Header Injection<br/>Polluted defaults.headers slot rides along on every outbound axios request\"]\n ROOT --> CLASS_B[\"B. Crash DoS via Object.prototype.get / .set<br/>Polluted descriptor breaks Object.defineProperty in mergeConfig\"]\n\n CLASS_A --> PRE_A[\"Precondition: header not set per-request by the app<br/>Injected via defaults.headers slot<br/>(common, delete, head, post, put, patch, query)\"]\n\n PRE_A --> PA1[\"Response Suppression<br/>Trigger: common = {If-None-Match: *}<br/>Affects GET / HEAD\"]\n PA1 --> SA1[\"DoS<br/>304 Not Modified empty\"]\n\n PRE_A --> PA2[\"Server Hang<br/>Trigger: common = {Content-Length: 99999}<br/>Affects requests with body\"]\n PA2 --> SA2[\"DoS<br/>connection hang\"]\n\n PRE_A --> PA3[\"CL+TE Conflict<br/>Trigger: common = {Transfer-Encoding: chunked}<br/>Affects requests with body\"]\n PA3 --> SA3[\"DoS<br/>400 Bad Request\"]\n\n CLASS_B --> SB1[\"DoS<br/>TypeError: Getter / Setter must be a function<br/>Crashes every axios request, not only GET\"]\n\n %% Styles\n style ROOT fill:#f87171,stroke:#991b1b,color:#fff\n style CLASS_A fill:#fb923c,stroke:#9a3412,color:#fff\n style CLASS_B fill:#fb923c,stroke:#9a3412,color:#fff\n style PRE_A fill:#e2e8f0,stroke:#64748b,color:#1e293b\n style PA1 fill:#fbbf24,stroke:#92400e,color:#000\n style PA2 fill:#fbbf24,stroke:#92400e,color:#000\n style PA3 fill:#fbbf24,stroke:#92400e,color:#000\n style SA1 fill:#ef4444,stroke:#991b1b,color:#fff\n style SA2 fill:#ef4444,stroke:#991b1b,color:#fff\n style SA3 fill:#ef4444,stroke:#991b1b,color:#fff\n style SB1 fill:#ef4444,stroke:#991b1b,color:#fff\n```\n\n## Root Cause\n\n**Finding A.** `lib/utils.js:404-429`'s `merge()` creates `result = {}` at line 406. The dangerous-keys filter on lines 408-411 blocks the write side, but the read at line 414 (`isPlainObject(result[targetKey])`) still walks the prototype chain. When `targetKey` matches a polluted slot, `result[targetKey]` returns the polluted nested object, and the recursive `merge(result[targetKey], val)` on line 415 iterates that object's own keys via `forEach` and copies them as own properties into the new accumulator. Those keys flow through `mergeConfig.js:35` → `Axios.js:148` (`utils.merge(headers.common, headers[config.method])`) → `Axios.js:155` (`AxiosHeaders.concat(...)`) → onto the wire via `http.js:677` (`headers: headers.toJSON()`) → `http.js:767` (`transport.request(options, ...)`).\n\n**Finding B.** `lib/core/mergeConfig.js:25` correctly makes `config = Object.create(null)`, but the descriptor passed on line 26 is a plain-object literal - its `get`/`set` lookups walk `Object.prototype`. A polluted non-function `Object.prototype.get` or `.set` makes `Object.defineProperty` throw `TypeError: Getter must be a function` (or `Setter must be a function`) before the call returns. The descriptor is built unconditionally on every `mergeConfig` invocation, so every axios request throws - POST, PUT, DELETE, PATCH, HEAD, QUERY, not only GET.\n\n## Suggested Fix\n\nUse null-prototype objects in place of the plain-object literals at `lib/utils.js:406` and `lib/core/mergeConfig.js:26-31`. The same descriptor pattern recurs at `lib/core/AxiosError.js:37`, `lib/core/AxiosHeaders.js:100`, `lib/utils.js:447/454/492/498`, and `lib/adapters/adapters.js:28/32`.\n\n## Resources\n\n- [CVE-2018-16487](https://nvd.nist.gov/vuln/detail/CVE-2018-16487) - `lodash.merge` prototype pollution in `lodash <= 4.17.10`\n- [CWE-1321](https://cwe.mitre.org/data/definitions/1321.html) - Improperly Controlled Modification of Object Prototype Attributes",
"severity" : [ {
"type" : "CVSS_V3",
"score" : "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:L"
} ],
"affected" : [ {
"package" : {
"ecosystem" : "npm",
"name" : "axios"
},
"ranges" : [ {
"type" : "ECOSYSTEM",
"events" : [ {
"introduced" : "1.0.0"
}, {
"fixed" : "1.16.0"
} ]
} ]
}, {
"package" : {
"ecosystem" : "npm",
"name" : "axios"
},
"ranges" : [ {
"type" : "ECOSYSTEM",
"events" : [ {
"introduced" : "0"
}, {
"fixed" : "0.32.0"
} ]
} ],
"database_specific" : {
"last_known_affected_version_range" : "<= 0.31.1"
}
} ],
"references" : [ {
"type" : "WEB",
"url" : "https://github.com/axios/axios/security/advisories/GHSA-898c-q2cr-xwhg"
}, {
"type" : "ADVISORY",
"url" : "https://nvd.nist.gov/vuln/detail/CVE-2018-16487"
}, {
"type" : "ADVISORY",
"url" : "https://nvd.nist.gov/vuln/detail/CVE-2026-44490"
}, {
"type" : "PACKAGE",
"url" : "https://github.com/axios/axios"
} ],
"database_specific" : {
"cwe_ids" : [ "CWE-1321" ],
"severity" : "MODERATE",
"github_reviewed" : true,
"github_reviewed_at" : "2026-05-29T15:54:57Z",
"nvd_published_at" : "2026-06-11T17:16:33Z"
}
}