Axios had a brutal start to April 2026. On March 31, two malicious Axios releases, 1.14.1 and 0.30.4, were published to npm through a compromised maintainer account and were later removed. A week later, Axios shipped v1.15.0 with two critical security fixes, one for a NO_PROXY normalization bug tracked as CVE-2025-62718 and one for CVE-2026-40175, the header-injection gadget chain now getting most of the attention. That sequence matters because many teams are triaging “Axios risk” as if it were one problem. It is not. There is a supply-chain compromise, there is an SSRF-related proxy-bypass bug, and there is this newer header-injection chain that can, in the worst reading, escalate prototype pollution somewhere else in your stack into SSRF, request smuggling, and even cloud metadata abuse. (GitHub)
If you only take one operational step after reading this, make it simple: move every Axios deployment you control to 1.15.0 or later, then verify whether any part of your server-side request path can inherit attacker-controlled properties or build headers from polluted objects. That is the safest interpretation of the official record, and it is the only interpretation that still holds even if some of the worst-case headlines turn out to overstate practical exploitability in your exact runtime. The problem here is not just “Axios has a bad parser” or “Axios allows raw header injection.” The deeper issue is that Axios sits on a trust boundary that many teams do not model carefully enough: object merging, inherited properties, outbound destination control, proxy rules, and credential-bearing internal requests. (GitHub)
The official description of CVE-2026-40175 is dramatic for a reason. GitHub’s advisory says the library can act as a gadget chain in which prototype pollution in some other dependency is escalated into remote code execution or full cloud compromise through unsanitized outgoing headers and default SSRF capability. NVD repeats the same core description and points to Axios 1.15.0 as the fixed release. But the public record is not neat. The GitHub advisory page itself is internally inconsistent about affected versions and even inconsistent in how it presents severity. That does not make the issue fake. It does mean that responsible engineering teams should read past the score, understand the mechanics, and test the path that actually exists in their environment. (GitHub)
CVE-2026-40175 in one paragraph
At its core, CVE-2026-40175 is a chained server-side risk. The advisory says Axios can consume polluted properties from Object.prototype during config merging, fail to reject CRLF characters in outgoing header values, and turn those values into a request-smuggling or SSRF primitive. The published proof-of-concept narrative targets AWS IMDSv2 by crafting a second request that performs the required PUT token exchange and then uses the returned token to retrieve metadata. That is why the public headlines talk about cloud compromise rather than a generic header-validation bug. The issue is fixed in Axios 1.15.0. (GitHub)
That one-paragraph summary is useful, but it still hides the hardest part of triage. This is not a bug you can assess just by asking, “Do we use Axios?” It depends on whether polluted properties can realistically reach the request config, whether your runtime will let those header values survive long enough to hit the wire, whether your workload can reach internal services or the instance metadata service, and whether you have already constrained that path with network or platform controls. In other words, the advisory describes the maximum credible chain. Your real task is to measure the reachable chain. (GitHub)
A useful way to think about CVE-2026-40175 is that it exposes the cost of treating outbound HTTP as “just a library call.” In a mature system, outbound requests are not boring. They may carry identity, session cookies, signed headers, internal routing information, service-to-service credentials, and access to internal-only destinations. When a library that builds those requests starts inheriting attacker-controlled state from the JavaScript prototype chain, the problem is not merely malformed syntax. The problem is that a previously trusted boundary, the point where your application constructs and emits requests, has become programmable by something upstream that the developer may never even connect to the request path. That is exactly why this record deserves more attention than a generic CRLF-in-header headline would suggest. (GitHub)
What the official CVE-2026-40175 record actually says
The most reliable starting point is the GitHub advisory and the NVD entry, because the NVD record is still marked as undergoing analysis and points back to GitHub as the CNA source. The GitHub advisory says the package is axios, the patched version is >=1.15.0, the vulnerable component is lib/adapters/http.js, and the chain involves prototype pollution, CRLF-based header injection, request smuggling, SSRF, and IMDSv2 bypass. It also names the relevant CWEs as CWE-113, CWE-444, and CWE-918. NVD mirrors that framing and also points to the fix commit, the pull request, the release page, and the advisory itself. (GitHub)
The advisory also includes a detail that too many summaries skip: it describes this as requiring no direct user input to Axios itself. The attacker does not necessarily need to hand Axios a malicious header object in the application code that the developer can see. The advisory’s model is that some other vulnerable library in the stack allows Object.prototype to be polluted, and Axios later picks up those polluted properties when it merges request configuration. That is a different threat model from the classic “user-controlled header value reaches a request API.” It is quieter, more indirect, and easier to miss in code review because the application’s Axios call can look completely harmless. (GitHub)
The official record is also messy enough that it would be irresponsible to pretend otherwise. On the same GitHub advisory page, the top metadata box lists affected versions as <1.13.2, but the narrative text in the description says “Affected Versions: All versions, v0.x – v1.x,” while NVD states “Prior to 1.15.0.” The severity presentation is similarly uneven: the description text says “CVSS 9.9,” while the advisory’s score panel shows 10.0, and NVD renders the GitHub CNA vector as 10.0 Critical while still showing that NVD’s own assessment is not yet provided. Those inconsistencies do not invalidate the record. They do change how a careful team should consume it. The correct operational response is not to debate whether 1.13.2 or 1.15.0 is the true boundary. The correct response is to standardize on 1.15.0 or newer, because every official path agrees that 1.15.0 contains the fix. (GitHub)
That kind of inconsistency is more than paperwork. It affects risk ownership. Security teams want to know whether an image tagged with Axios 1.13.5 is exposed. Dependency bots want a precise floor. Platform teams want to know whether every 0.x build is in scope. Procurement and audit teams want a single severity number. Here, the public record does not provide that cleanly. When the record is inconsistent, your change window should get more conservative, not less. A good internal note for this CVE is simple: “Treat all Axios versions below 1.15.0 as requiring remediation for CVE triage purposes, and verify in runtime whether the chain is reachable.” That phrasing is honest to the sources and much safer than pretending the ambiguity is not there. (GitHub)
Here is the cleanest way to read the public record:
| Public source | What it says | What you should do |
|---|---|---|
| GitHub advisory metadata | Affected versions <1.13.2, patched >=1.15.0 | Do not rely on the narrow range alone |
| GitHub advisory narrative | All versions v0.x - v1.x, critical chain through prototype pollution and header injection | Treat the issue as a chained server-side risk |
| NVD entry | Prior to 1.15.0, fixed in 1.15.0, record still under analysis | Use 1.15.0 as the remediation floor |
| Axios release note | v1.15.0 contains the header injection fix and the NO_PROXY SSRF fix | Patch directly to v1.15.0 or later |
The table looks mundane, but it reflects the main engineering lesson of this CVE: you cannot automate your judgment away by copying one field from one advisory page. You have to reconcile the record. (GitHub)

Why CVE-2026-40175 is a gadget chain, not a stand-alone bug
The phrase “gadget chain” is doing real work here. MDN’s explanation of prototype pollution is a good lens for this CVE because it breaks the problem into two phases: pollution and exploitation. First, an attacker manages to add or modify properties on a prototype, often Object.prototype. Second, ordinary application code accesses those polluted properties and behaves differently than the developer intended. The exploit does not necessarily come from the same code that created the pollution. It comes from whatever trusted logic later consumes the polluted state. (MDN Web Docs)
That is exactly how the GitHub advisory frames Axios. According to the advisory, if some other library in the stack makes it possible to pollute Object.prototype, Axios can later inherit those properties when it merges configuration for an outbound request. The application’s request can be hardcoded and look perfectly safe. The dangerous part is not the URL literal in the source file. The dangerous part is the inherited header state that was never supposed to be there. That is why the advisory calls out example upstream libraries such as qs, minimist, ini, and body-parser. Whether or not your exact stack uses those packages is less important than the pattern: a pollution bug somewhere else becomes weaponizable because Axios becomes the execution gadget later in the chain. (GitHub)
Once you accept that framing, the rest of the chain becomes easier to reason about. Prototype pollution gives the attacker a way to place values onto inherited properties. Axios, according to the advisory, merges those properties into headers. Header values containing CRLF are not neutralized. That means a single header value can change the structure of the request stream, effectively splitting or smuggling additional request content. From there, the chain can turn into SSRF or request smuggling against destinations the developer did not intend to contact. The advisory’s highest-impact example is AWS IMDSv2, but the same structural issue also implies other risks, including injecting Cookie or Authorization headers toward internal management endpoints or using Host manipulation to poison shared caches. (GitHub)
That is why CVE-2026-40175 should not be reduced to “header injection in Axios.” The vulnerability lives at the intersection of three security models that are often owned by different people on the same team. One owner thinks about dependency risk and prototype pollution. Another owner thinks about outbound HTTP, proxies, and service calls. A third owner thinks about cloud metadata access and internal network segmentation. The Axios advisory crosses all three. The attack only becomes serious because each layer trusts the previous one. The polluted object is trusted by application logic. The application logic is trusted by the HTTP library. The HTTP request path is trusted by the cloud or internal network because it originates from the workload itself. Gadget chains are dangerous because they turn trust composition into exploit composition. (GitHub)
A lot of incident response pain starts when teams search for “the bug” in the wrong place. In a gadget-chain vulnerability, the place where the visible damage happens is often not the place where attacker control first enters the system. For CVE-2026-40175, that means you can patch Axios and still miss why the issue mattered. If your codebase accepts arbitrary object keys from query strings, JSON blobs, parser outputs, or helper libraries and later reuses plain objects to represent headers, request options, or auth state, then Axios is not your only boundary problem. Axios is the part that made the chain obvious enough to get a CVE. The upstream conditions that make such chains possible are often scattered throughout the codebase. That is why a good remediation plan always includes both library patching and a small review of how your project handles inherited properties. (MDN Web Docs)
You can see the same broader pattern in Penligent’s own Axios-focused writeup, which argues that the recurring issue is not “Axios is buggy” in a vague sense, but that Axios often sits in security-relevant decision points around destination, headers, token propagation, parsing, and object merging. That framing is useful because it pulls triage away from a single sensational phrase like “full cloud compromise” and toward a more durable question: what exactly in your environment is Axios trusted to decide or carry? If the answer includes internal hosts, privileged metadata endpoints, or high-value service-to-service credentials, then this record deserves real attention even before you decide how reachable the published chain is in practice. (penligent.ai)
The most important operational takeaway from the gadget-chain framing is that you should not limit review to code that says headers: req.headers or something equally obvious. You also need to look at helper functions that merge config objects, wrappers that build request options from multiple sources, auth middleware that stamps cookies or bearer tokens onto outgoing requests, and any place that still treats a plain JavaScript object as a safe bag of key-value pairs without checking ownership of the keys. Gadget chains live in the places where “boring plumbing” meets inherited state. (GitHub)
How the Axios header-injection chain reaches IMDSv2
The AWS angle is not there for drama. It is there because IMDSv2 changes what a “normal SSRF” can do. AWS’s documentation is explicit: to use IMDSv2, the caller first sends a PUT request to /latest/api/token with the X-aws-ec2-metadata-token-ttl-seconds header. The service returns a token. Subsequent metadata requests then have to include that token header. AWS also notes that when token use is required, requests without a valid token receive 401 Unauthorized, and the token is instance-specific. (AWS Documentation)
That matters because many SSRF primitives are weaker than headlines suggest. A lot of SSRF bugs let the attacker influence the destination URL but not the method, not the full header set, and not the structure of the raw request stream. If all you can do is force a plain GET to 169.254.169.254, IMDSv2 may stop you. The GitHub advisory’s impact story relies on that distinction. The point of the CRLF-based request-smuggling chain is not simply “send a request to metadata.” The point is to construct the specific additional request material needed to perform the IMDSv2 token exchange that a weaker SSRF cannot normally perform. (GitHub)
That is also why the advisory’s proof-of-concept narrative talks about a “smuggled second request.” In the advisory’s version of the chain, the malicious header value does not just inject a stray extra line. It alters the structure of the outbound HTTP stream so that the next request looks like a valid metadata token request. Once that token exists, the attacker can pivot to the usual metadata targets, including IAM role credentials where present. AWS’s own examples show exactly that token flow and make clear that the PUT request must include the TTL header and that the token must then be reused in later requests. (GitHub)
There is another subtle AWS detail worth noticing. AWS documents that IMDSv2 PUT requests are rejected if they contain an X-Forwarded-For header, and that the default response hop limit for those PUT responses is 1. Those are platform-level constraints, not silver bullets, but they illustrate an important point: the exact shape of the request path matters. Not every request path from your process to metadata is equivalent. Transparent proxies, sidecars, odd custom transports, container networking, and middleware that injects forwarding headers can all change whether a theoretical chain is actually usable. That is one more reason to validate in the real environment instead of assuming the advisory’s maximum-impact path maps one-to-one onto your deployment. (AWS Documentation)
For defenders, the practical lesson is straightforward. If your workload never needs metadata access at runtime, do not treat IMDS as somebody else’s concern just because the bug is “in Axios.” The published chain is only scary because the outbound request boundary and the cloud control boundary are so close together. The library is not stealing cloud credentials on its own. The library is potentially giving an attacker a way to make the workload talk to a privileged platform service that should have been treated as hostile territory from the application’s point of view. In other words, CVE-2026-40175 is partly a library bug and partly a reminder that link-local metadata services are part of your application’s attack surface whenever the process can reach them. (GitHub)
A lot of cloud compromise writeups flatten that distinction into a single sentence like “RCE to AWS takeover.” That phrasing is attractive, but it hides the middle. The middle is where real defenders work: can the process reach 169.254.169.254; is IMDSv2 required; are headers constrained; does the request path preserve the injected structure; does the instance role have meaningful privileges; is there any outbound policy or workload isolation in front of metadata; and does the application even have a pollution primitive elsewhere in the stack. Until you answer those questions, you do not know whether the advisory’s cloud-compromise story is a reachable risk or a worst-case diagram. (GitHub)

Why Node.js runtime behavior changes the practical risk
This is the part many public summaries skip because it is harder to turn into a headline. Node.js’s current HTTP documentation states that header values are automatically validated by the HTTP module, that invalid values raise a TypeError, and that invalid value characters are identified with ERR_INVALID_CHAR. The docs even say you do not need to call validateHeaderValue yourself before passing headers to a request, because the module automatically validates them. That is a strong platform-level constraint on any exploit path that depends on raw CRLF characters surviving into a standard Node HTTP request. (nodejs.org)
This behavior is not a brand-new Node hardening change that landed yesterday. Searchable Node.js documentation for older releases, including v9 and v10-era docs, already described ERR_INVALID_CHAR for headers. That does not prove every possible runtime path has always behaved identically, but it does mean that “Node rejects invalid header characters” is not some exotic new condition that only cutting-edge users benefit from. It has been a documented property of the platform for years. (nodejs.org)
That creates a genuine tension in the public record. The Axios advisory describes the chain as though the malformed header value can be written directly to the socket and turned into a smuggled second request. The Axios patch, meanwhile, explicitly hardens the library by rejecting CRLF in header values before those values ever reach the underlying request path. The pull request summary says Axios added assertValidHeaderValue, applied the validation to all header-set paths including array elements, and added or updated tests for the browser adapter, Node fetch, Node http, and AxiosHeaders. That patch is real and necessary. But the Node documentation also suggests that, in standard Node HTTP usage, invalid CRLF-bearing header values were already in conflict with the runtime’s own validation rules. (GitHub)
The right way to state that, carefully, is not “the CVE is fake” and not “the CVE guarantees easy cloud compromise.” The careful statement is this: the advisory describes a worst-case chain at the library level, but the practical reachability of that chain in a normal Node deployment depends on whether downstream runtime validation, adapter behavior, or custom transport logic blocks the malformed header before it becomes on-the-wire request structure. That is exactly the kind of environment-specific question that CVSS alone cannot answer for you. (GitHub)
There is an easy but dangerous mistake here: assuming runtime validation makes the patch optional. It does not. First, the official fixed version is still 1.15.0, and the library clearly chose to enforce the constraint itself instead of relying on whatever adapter or runtime sits below it. Second, the patch applies across multiple adapters, not just one Node code path. Third, security boundaries that “usually exist downstream” are brittle places to stop remediation. Good security engineering prefers explicit validation at the layer where the risk is introduced. Axios clearly agreed with that judgment when it shipped the fix. (GitHub)
It is also worth remembering that many real-world Axios deployments do not use the most boring possible path. They may wrap Axios with custom abstractions, combine it with polyfills or alternative runtimes, route it through special proxies, or transform headers before dispatch. The published patch and the Node docs together tell you the right question to ask in testing: “Does my actual request path reject CRLF-bearing header values before they can alter the request structure?” That is a much better verification target than arguing about headlines on social media. (nodejs.org)
A mature response to CVE-2026-40175 therefore has two parts. The first part is mechanical: upgrade to 1.15.0 or later, remove the advisory condition from your dependency graph, and catch future regressions in CI. The second part is empirical: run a negative test in your own stack and confirm that invalid header content is rejected where you think it is rejected. That second part is what turns a patch from a version bump into a verified control. (GitHub)

What Axios changed in 1.15.0
Axios’s v1.15.0 release note is terse but important. It says the release contains two critical security patches, one for proxy handling and one for header injection, and explicitly calls out “Header Injection: Fixed an unrestricted cloud metadata exfiltration vulnerability via a header injection chain.” That means you do not need to guess whether the maintainers consider this fixed in that release. They do. (GitHub)
The patch details in the commit and pull request make the fix more concrete. Axios added a header-value validation helper, rejected CRLF in any header value, applied that check to array values as well as single values, and enforced the validation in header-setting paths. The pull request summary is especially useful because it spells out the behavioral change: headers containing CR or LF are rejected with “Invalid character in header content,” and regression coverage was added for the browser adapter, the Node fetch adapter, the Node http adapter, and AxiosHeaders. That is the kind of patch you want to see for this class of issue because it collapses ambiguity at the library boundary instead of leaving it to downstream behavior. (GitHub)
The patch also says something about security philosophy. Before the fix, even if a downstream runtime was likely to reject malformed header values, Axios was still willing to carry those values far enough that a published advisory could plausibly frame the library as a gadget in a larger chain. After the fix, Axios makes that kind of unsafe header state invalid much earlier. In practical terms, that moves the failure point closer to the application and makes testing much easier. A rejected request in the client library is far easier to reason about than a runtime-specific failure deeper in the stack. (GitHub)
The fact that v1.15.0 also fixes CVE-2025-62718 is another reason not to get clever about partial upgrades. The release note says the proxy-handling fix closes a NO_PROXY hostname normalization bypass that could lead to SSRF. NVD’s description of CVE-2025-62718 says Axios failed to normalize hostnames like localhost. or [::1] properly against NO_PROXY, causing traffic to go through a configured proxy when developers expected loopback or internal traffic to bypass it. That is a separate bug, but it lives in the same broad territory: outbound trust boundaries, SSRF assumptions, and requests going somewhere the operator did not mean them to go. If you are already touching Axios, go straight to the version that fixes both. (GitHub)
Here is the kind of post-upgrade unit test that is worth adding to your own suite, even if you never try to reproduce the full advisory chain:
import axios from "axios";
test("rejects CRLF in outgoing header values", async () => {
await expect(
axios.get("http://127.0.0.1:3000/health", {
headers: {
"x-test": "safe\r\nInjected: yes"
},
timeout: 1000
})
).rejects.toThrow(/Invalid character/i);
});
That is not an exploit test. It is a boundary test. It asserts that your request path now fails where it should fail. The Axios PR summary indicates that this “invalid header content” rejection is exactly the behavior the patch is meant to enforce. (GitHub)
Who should treat CVE-2026-40175 as urgent
The highest-priority group is server-side Node applications that use Axios to reach internal services, metadata endpoints, control planes, or privileged APIs. The advisory’s main impact story is server-side and cloud-oriented, not browser-only and user-interface-oriented. If your workload sits on EC2 or an equivalent environment where metadata access matters, and if Axios calls are used for internal service communication or admin-plane reachability, this CVE should be near the top of your dependency remediation list. (GitHub)
The next group is teams with any history of prototype-pollution exposure, or code patterns that make pollution more likely to matter. MDN and OWASP both emphasize that prototype pollution becomes dangerous when polluted properties are later consumed as if they were ordinary object state. That means projects that still use plain objects heavily for config, headers, flags, merge targets, or dynamic option bags deserve more scrutiny than codebases that already isolate such state with null-prototype objects, Map, or strict ownership checks. In other words, the same Axios version can represent very different practical risk in two different codebases. (MDN Web Docs)
Teams that use Axios entirely in browser-side code should still patch, but they should reason about impact differently. The headline cloud-compromise path depends on server-side network position and access to instance metadata. That specific story does not map cleanly onto the typical browser execution model. What does still matter in browser contexts is that Axios chose to reject invalid CRLF-bearing header values across adapters and added browser-related regression tests, which means the fix is not “server only.” The responsible posture is still to update, just without assuming every sensational server-side impact claim applies equally to the browser. (GitHub)
A simple way to prioritize:
| Environment | Why it matters for CVE-2026-40175 | Priority |
|---|---|---|
| Node services on cloud instances | Potential metadata reachability and privileged service-to-service traffic | Highest |
| API gateways, workers, internal microservices | Heavy outbound request construction and internal trust assumptions | High |
| Apps with known parser or merge risk | Prototype pollution elsewhere can become the entry point | High |
| Browser-only frontends | Fix still matters, but the cloud metadata impact path is less direct | Medium |
| Dead code or pinned old build artifacts | Still patch, but urgency depends on runtime reachability | Case by case |
The point of a table like this is not to downgrade the issue. It is to stop wasting time on a false binary where the only options are “trivial RCE everywhere” or “nothingburger.” This record sits in between. For the wrong environment, it is dangerous. For the average environment, it still deserves a fast patch and a quick validation pass. (GitHub)
How to find Axios exposure in a real codebase
Start with the version inventory, but do not stop there. In JavaScript ecosystems, the direct dependency you remember adding is often not the version that actually matters in the deployed graph. Lock files, transitive dependencies, base images, and workspace-level package managers all matter. The quickest first pass is still the old-fashioned one:
npm ls axios
yarn why axios
pnpm why axios
That tells you where Axios is present and whether you are dealing with a direct dependency or a transitive one. It will not tell you whether a container image or build pipeline still bakes in an old copy elsewhere, but it gives you the immediate dependency graph to fix. The reason this matters is simple: GitHub’s Dependabot and dependency graph logic are strongest when the vulnerable package exists in a manifest or lock file, but real organizations also run software through image layers, cached build contexts, and monorepo boundaries that simple manifest scanning does not fully capture. (GitHub Docs)
If your environment includes monorepos or multiple lockfiles, search the repository instead of assuming one top-level answer is enough:
find . -name package-lock.json -o -name yarn.lock -o -name pnpm-lock.yaml
grep -R "\"axios\"" .
Then review each package boundary and deployment target. The operational goal is not just “prove the repo depends on Axios.” The goal is to answer a stricter question: which deployed artifacts still resolve Axios below 1.15.0, and which of those artifacts can make server-side outbound requests into sensitive network space. That second question is the one the CVE actually cares about. (nvd.nist.gov)
You should also split one special case out immediately: the March 31 malicious Axios releases are not the same incident as CVE-2026-40175. The official Axios post-mortem says versions 1.14.1 and 0.30.4 were maliciously published through a compromised account, were live for about three hours, and should be treated as machine compromise if installed during that window. The post-mortem even provides a lockfile grep pattern and remediation steps such as rotating secrets and checking for plain-crypto-js. That deserves its own checklist item because a team that says “we upgraded to 1.15.0” may still miss the fact that a CI runner or developer workstation previously installed one of the malicious releases. (GitHub)
A useful triage note for internal tickets is this:
grep -E "axios@(1\.14\.1|0\.30\.4)|plain-crypto-js" package-lock.json yarn.lock 2>/dev/null
That command is straight out of the official post-mortem and is worth running anywhere you suspect fresh installs occurred during the affected window. Keep it separate from the CVE ticket so ownership stays clear. One item is a dependency vulnerability. The other is a supply-chain compromise response. (GitHub)
Once version inventory is done, add one small code review pass targeted at ownership of request config. Look for wrappers that merge options from several sources, helper objects that accumulate headers over time, and any use of plain object iteration over potentially untrusted input. This is where the CVE becomes real or stays theoretical. A project that never uses inherited properties in request config is in a much better place than a project that constantly mixes user-shaped objects into request options. MDN’s guidance on prototype pollution is especially relevant here: prefer Object.keys() over for...in, check ownership with Object.hasOwn(), and use null-prototype objects where options objects are unavoidable. (MDN Web Docs)
How to patch Axios safely in npm, Yarn, and pnpm
If Axios is a direct dependency, the patch path is the easy one:
npm install axios@^1.15.0
# or
yarn add axios@^1.15.0
# or
pnpm add axios@^1.15.0
The harder cases are the ones where Axios is transitive and the direct dependency has not updated yet. That is where package-manager override features stop being a convenience and become a security control. npm’s official docs say the overrides field exists specifically to replace versions in the dependency tree, including when a dependency of a dependency has a known security issue. Yarn’s resolutions feature is explicitly documented as a way to pin sub-dependencies when you do not want to wait for the direct dependency to issue a new minimum version. pnpm provides an overrides feature at the project root for the same reason. (docs.npmjs.com)
For npm, a short-term forced lift looks like this:
{
"overrides": {
"axios": "1.15.0"
}
}
For Yarn Classic, the equivalent pattern is:
{
"resolutions": {
"**/axios": "1.15.0"
}
}
For pnpm, place the override at the workspace root:
overrides:
axios: 1.15.0
These are not forever solutions. They are bridge controls that let you collapse risk faster than your slowest upstream maintainer. Once the direct dependency catches up, remove the emergency pin and return to a normal update path. (docs.npmjs.com)
Patching once is not enough if the same class of regression can quietly re-enter the tree next week. That is where GitHub’s supply-chain controls are useful. GitHub’s documentation says Dependabot security updates can automatically open pull requests to update vulnerable dependencies to the minimum patched version that resolves the alert, and that the feature works off the repository’s dependency graph and lockfiles. The dependency review action can also fail pull requests that introduce known vulnerable dependencies, and GitHub’s docs show exactly how to set fail-on-severity in a workflow. (GitHub Docs)
A minimal workflow worth keeping in place after this incident looks like this:
name: Dependency review
on:
pull_request:
branches: [ "main" ]
permissions:
contents: read
jobs:
dependency-review:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v5
- name: Dependency Review
uses: actions/dependency-review-action@v4
with:
fail-on-severity: critical
That example is directly aligned with GitHub’s documentation. It will not solve every supply-chain blind spot, but it does raise the cost of reintroducing a known critical package through ordinary pull request flow. For ecosystems where patch adoption lags, that is often enough to turn “we should probably update later” into a blocked merge. (GitHub Docs)
There is also a second CI lesson hidden in Axios’s own release notes and post-mortem. After the March 31 compromise, Axios’s v1.15.0 release notes say the project hardened CI permissions, pinned action versions, added zizmor, and gated npm publishing with OIDC and environment protection. That is not directly part of CVE-2026-40175, but it is the right broader lesson: dependency risk does not stop at version numbers. The path by which packages are published, reviewed, and consumed matters too. If your organization still treats dependency updates as a quarterly hygiene exercise rather than an actively enforced control plane, Axios has now given you several reasons to rethink that stance. (GitHub)

How to harden against prototype pollution after CVE-2026-40175
Patching Axios closes the published library boundary. It does not remove the pollution conditions that made Axios useful as a gadget in the first place. MDN’s prototype pollution guidance is unusually practical here. It recommends checking ownership with Object.hasOwn(), avoiding for...in when iterating potentially attacker-shaped objects, creating null-prototype objects for option bags, and using Map or Set instead of ad hoc objects when possible. Those are not abstract style preferences. They directly reduce the chance that inherited properties silently influence application behavior. (MDN Web Docs)
For request construction code, null-prototype objects are especially relevant. MDN explicitly says that null-prototype objects avoid both pollution of __proto__ and lookups on the prototype. OWASP’s cheat sheet makes the same recommendation and shows Object.create(null) as the safe construction pattern when objects must be used. That maps almost perfectly onto the kinds of option objects developers pass into HTTP clients. If you are building headers or request options dynamically, the difference between {} and Object.create(null) is not cosmetic in a codebase that cares about prototype pollution. (MDN Web Docs)
A safer request-construction pattern looks like this:
function buildSafeHeaders(input) {
const headers = Object.create(null);
for (const key of Object.keys(input)) {
const value = input[key];
if (typeof value !== "string") continue;
if (/[\r\n]/.test(value)) throw new Error("Invalid header content");
headers[key] = value;
}
return headers;
}
The point is not that every team must write this helper exactly. The point is that safe request construction needs three properties: own-key iteration, explicit validation, and no ambient prototype inheritance. That is the mindset CVE-2026-40175 is trying to force back into the conversation. (MDN Web Docs)
When objects are not the right structure, use the right structure instead of arguing with the prototype chain. OWASP recommends Map and Set because they do not resolve lookups through Object.prototype. MDN makes the same point. In practice, this is a good fit for configuration flags, header templates, allowlists, destination controls, and other key-value state that engineers often reach for plain objects to represent by habit. A Map is not just cleaner in some of these cases. It is structurally less vulnerable to prototype-shaped surprises. (cheatsheetseries.owasp.org)
Node also gives you a defense-in-depth control that is worth knowing about even if it is not a complete answer. OWASP’s cheat sheet notes that Node can remove __proto__ using the --disable-proto=delete flag. The cheat sheet is clear that this is not a full fix because pollution can still occur through constructor.prototype, but it does reduce attack surface and can prevent some classes of exploit chains from behaving the way they would in default environments. This is the sort of control that belongs in hardened production runtimes and in the conversation with platform engineering, not as a substitute for patching or code review. (cheatsheetseries.owasp.org)
The other half of hardening is network-level reality. AWS’s IMDSv2 documentation reminds you that metadata access is still just an HTTP path from the workload’s point of view. If the process does not need metadata, treat access to 169.254.169.254 as a privilege to remove, not a default to tolerate. Keep IMDSv2 required where applicable, keep the hop limit tight unless you have a documented reason to raise it, and avoid normalizing the idea that every workload should be able to talk to metadata forever just because that is the default on day one. The Axios advisory is a library reminder of a cloud truth defenders already know: internal platform services are still attack surface when application code can reach them. (AWS Documentation)
There is a reporting lesson here too. Penligent’s public material on AI pentest reporting makes a point that is directly relevant to this kind of CVE validation: a trustworthy security output is not polished prose, it is a reproducible evidence chain that another human can retest. That is exactly the right standard for CVE-2026-40175. You do not need a beautiful PDF saying “critical cloud compromise.” You need a record of which versions were present, which runtime rejected what, which outbound paths were reachable, which controls blocked metadata access, and what changed after the fix. That is a better use of security automation than turning headlines into longer headlines. (penligent.ai)
How to verify the fix instead of just updating the version
A version bump is a claim. Verification is evidence. After upgrading to Axios 1.15.0 or later, you want to prove four things. First, the dependency graph no longer resolves a vulnerable Axios version. Second, invalid CRLF-bearing header values are rejected in your real request path. Third, polluted inherited properties do not silently become request config. Fourth, the application cannot reach privileged internal destinations in ways you did not intend. Those are four different checks, and all of them matter more than a screenshot of a dependency alert turning green. (nvd.nist.gov)
Start with the easy negative tests. Add a request-level test that asserts Axios throws on CRLF in header values. The PR summary says that is now expected behavior across adapters. If your own wrapper swallows the error, transforms it, or retries strangely, that is useful information too. It means your application’s control plane around Axios still needs attention even if the library boundary is fixed. (GitHub)
Then test ownership boundaries explicitly. The same MDN page that explains prototype pollution also recommends Object.hasOwn() checks and warns against for...in over attacker-shaped objects. Use that advice to write one or two cheap regression tests around whatever helper in your codebase assembles outbound headers or options. If your helper still treats inherited values as ordinary config, the test should fail until you fix it. Those are the kinds of regressions that a dependency upgrade alone will not catch. (MDN Web Docs)
A simple sanity test for your own helper layer can look like this:
test("does not inherit polluted header keys", () => {
Object.prototype.evil = "x";
const opts = Object.create(null);
opts["x-safe"] = "1";
const seen = [];
for (const key of Object.keys(opts)) {
seen.push(key);
}
expect(seen).toEqual(["x-safe"]);
delete Object.prototype.evil;
});
That test is deliberately boring. Good boundary tests usually are. The goal is to make it impossible for inherited state to sneak back into the exact classes of objects that Axios later consumes. (MDN Web Docs)
Next, verify the network boundary. If your workload has no reason to read EC2 metadata at runtime, make that true in practice rather than in a policy deck. AWS documents the token requirement, the instance-specific token property, the hop-limit behavior, and the rejection of PUT requests carrying X-Forwarded-For. Those platform details give you useful negative test points. Your regression does not need to recreate the advisory’s full chain. It only needs to confirm that your application cannot complete a metadata-relevant path it should never have had in the first place. (AWS Documentation)
Finally, record the result in a way another engineer can retest. This is where automation can help if it is disciplined. Penligent’s AI pentest reporting material is right to insist on scope, reproducibility, artifacts, exploit conditions, and clear remediation proof. That is the bar you want here. A good internal validation note for CVE-2026-40175 should say exactly which image or package was upgraded, what negative tests were run, what network assumptions were checked, what remained out of scope, and what follow-up was required for upstream prototype-pollution hardening. Security work gets expensive when each retest starts from memory instead of evidence. (penligent.ai)
Why CVE-2025-62718 and the March 31 Axios compromise belong in the same triage window
Teams get into trouble when they process related events as unrelated tickets because the bugs have different numbers. Axios v1.15.0 did not just patch CVE-2026-40175. It also fixed CVE-2025-62718, a critical NO_PROXY hostname normalization bypass that could lead to SSRF by sending traffic through a configured proxy when developers expected loopback or internal traffic to bypass it. That is not the same mechanism as the header-injection chain, but the theme is close enough to matter: outbound request trust assumptions were wrong, and those wrong assumptions could have security impact. (GitHub)
Then there is the supply-chain issue. Axios’s official post-mortem says the malicious 1.14.1 and 0.30.4 releases added plain-crypto-js, installed a RAT on macOS, Windows, and Linux, and were live for about three hours before removal. That incident is operationally different from a CVE, but it lands in the same team inbox, on the same package name, at almost the same time. A mature response therefore groups the work as “Axios security event response” while still keeping the remediation tracks separate: compromise response for the malicious releases, dependency upgrade for the CVEs, validation for runtime and network reachability, and CI hardening for future prevention. (GitHub)
That broader framing is also why Penligent’s Axios writeup gets one thing right: the recurring problem is the outbound trust boundary. Some Axios issues are about where requests go. Some are about how headers are formed. Some are about proxy rules. Some are about release integrity. But they all touch the same strategic question: when your code emits a request, what hidden assumptions are you making about who shaped it, where it can travel, and what privileged systems will trust it once it leaves the process. That is a much more useful mental model than treating each advisory as an isolated meteor strike. (penligent.ai)
Closing thoughts on CVE-2026-40175
CVE-2026-40175 deserves a fast patch, but it also deserves a smarter conversation than most headline coverage gives it. The highest-impact public story, prototype pollution becoming header injection becoming SSRF becoming IMDSv2 abuse becoming cloud compromise, is serious enough to justify the urgency. At the same time, the public record around this CVE is inconsistent, the NVD entry is still under analysis, and Node’s documented header validation behavior means you should not confuse “critical advisory language” with “trivial exploitability in every standard deployment.” Both things can be true at once: the bug class is real, and the reachable chain is environment-dependent. (GitHub)
The mature engineering response is therefore not hard to describe. Patch to 1.15.0 or later. Inventory every deployed graph, not just the package you remember adding. Separate the March 31 malicious-release response from the CVE response. Review request-construction code for inherited state and weak object handling. Keep IMDS and internal control planes out of reach where they are not needed. Add CI controls so the same category of issue cannot quietly come back through another transitive update. And, most important, verify the control in your runtime instead of outsourcing your judgment to a score. (GitHub)
The real lesson of CVE-2026-40175 is not that Axios suddenly turned into magic RCE. The real lesson is that outbound trust boundaries are part of the attack surface, and inherited state in JavaScript can quietly reprogram those boundaries when teams treat “just an options object” as safe by default. That is the kind of lesson worth carrying forward after the dependency alert is closed. (GitHub)
Further reading for CVE-2026-40175
Authoritative external sources
- GitHub advisory for CVE-2026-40175, Axios header injection chain and published impact narrative. (GitHub)
- NVD entry for CVE-2026-40175, including references to the patch commit, pull request, and release page. (nvd.nist.gov)
- Axios v1.15.0 release note, which lists the header injection fix and the companion
NO_PROXYfix. (GitHub) - Axios fix pull request and patch summary, showing CRLF rejection across adapters and tests. (GitHub)
- AWS IMDSv2 documentation, for the actual token flow and request requirements that make the advisory’s cloud-impact story meaningful. (AWS Documentation)
- Node.js HTTP documentation, for automatic header validation and
ERR_INVALID_CHAR. (nodejs.org) - MDN and OWASP guidance on prototype pollution prevention, including
Object.hasOwn(), null-prototype objects,Map,Set, and Node defense-in-depth flags. (MDN Web Docs) - GitHub advisory and NVD record for CVE-2025-62718, the
NO_PROXYhostname normalization bypass leading to SSRF risk. (GitHub) - Official Axios post-mortem for the March 31, 2026 malicious npm releases. (GitHub)
- Penligent, Axios npm CVE, the real risk is your outbound trust boundary. (penligent.ai)
- Penligent, How to Get an AI Pentest Report. (penligent.ai)
- Penligent, AI Pentest Tool, What Real Automated Offense Looks Like in 2026. (penligent.ai)
- Penligent product overview page for automated penetration testing workflows. (penligent.ai)

