When teams search for “axios npm cve,” they usually expect a neat answer: one bug, one patch, one upgrade, done. Axios does not behave that way in the real world. The package sits at a boundary where untrusted input turns into outbound behavior. That boundary includes URL resolution, header propagation, cookie-derived token handling, configuration merging, and in Node.js even special handling for non-HTTP schemes. It now also includes something no ordinary vulnerability patch can solve by itself: a March 2026 npm compromise in which two Axios releases were turned into malware installers. (GitHub)
That distinction matters because not every Axios alert describes the same kind of failure. Some records are about server-side request forgery. Some are about sending security-sensitive headers to the wrong host. Some are about denial of service in Node-specific code paths that never send a network packet at all. Some are about configuration objects crashing the process before any request is made. One recent alert was withdrawn because the vulnerable component was a transitive dependency that could be patched independently. Another NVD entry is explicitly marked as disputed. If you flatten all of that into “Axios has a CVE,” you lose the engineering detail that tells you what to fix, what to investigate, and what to ignore. (GitHub)
The right way to read the Axios security record is to stop thinking about package popularity first and start thinking about trust boundaries first. Axios is the layer where developers often assume that a path is only a path, a callback URL is only a string, a cookie-derived token is only sent where it belongs, a content-length limit applies to every kind of input, or a parsed JSON object is safe to pass through as request config. Most of the interesting Axios security problems come from those assumptions breaking under attacker-controlled input. (Axios)
Axios npm CVE is not one record, it is a map of different failure modes
The easiest way to see the pattern is to put the records side by side. Once you do that, the recurring theme is not “Axios is buggy” in the abstract. The theme is that Axios often mediates security-relevant choices about destination, headers, token propagation, parsing, and object merging. Different CVEs hit different parts of that surface. (GitHub)
| Record | 카테고리 | 영향을 받는 버전 | Core issue | Fixed version or status |
|---|---|---|---|---|
| CVE-2023-45857 | Token leakage | >=1.0.0 <1.6.0, >=0.8.1 <0.28.0 | Axios could expose XSRF-TOKEN by sending X-XSRF-TOKEN to unintended hosts | 1.6.0, 0.28.0 |
| CVE-2024-39338 | SSRF | >=1.3.2 <=1.7.3 | Path-relative input could be processed as protocol-relative URL | 1.7.4 |
| CVE-2024-57965 | Disputed origin check record | 전에 1.7.8 | NVD notes a same-origin parsing concern, but also marks the record disputed | disputed, patch trail points to 1.7.8 |
| CVE-2025-27152 | SSRF and credential leakage | <=1.7.9, <=0.29.0 | Absolute URL can override baseURL, leaking headers or reaching unexpected hosts | 1.8.2, 0.30.0 |
| GHSA-rm8p-cx58-hcvx | Transitive dependency alert | [email protected] | Briefly tied Axios to [email protected], then withdrawn | withdrawn |
| CVE-2025-58754 | Node-specific DoS | 전에 0.30.2, before 1.12.0 | 데이터: URI handling decoded attacker-controlled payloads into memory | 0.30.2, 1.12.0 |
| CVE-2026-25639 | Config merge DoS | 전에 0.30.3, before 1.13.5 | mergeConfig crashed on objects containing own __proto__ | 0.30.3, 1.13.5 |
| March 2026 malicious releases | Registry compromise | 1.14.1, 0.30.4 | Official npm package was used to deliver malware through a hidden dependency | malicious versions removed |
Source basis for the table above comes from GitHub advisories, NVD entries, the withdrawn advisory notice, and the official Axios issue plus Microsoft’s incident write-up on the malicious npm releases. (GitHub)
One immediate takeaway is that “upgrade Axios” is not a sufficient security answer. For some records, upgrading is enough. For others, upgrading only removes one bad default while leaving a dangerous calling pattern intact. For the registry compromise, patching alone is the wrong mental model entirely, because affected systems may already have executed malicious install-time code and require incident response rather than ordinary dependency hygiene. (GitHub)
Axios lives where application trust becomes network trust
Axios’ own documentation makes the package’s role clear. The request config surface includes baseURL, allowAbsoluteUrls, withCredentials, xsrfCookieName, xsrfHeaderName, withXSRFToken, maxContentLength, maxBodyLength, redirect handling, proxy settings, and transport behavior. That is not just a convenience wrapper around HTTP; it is a control plane for how input becomes a request. When a package exposes that much policy-adjacent behavior, security issues tend to cluster where developers use convenience features as if they were security boundaries. (Axios)
OWASP’s SSRF guidance describes the kinds of business features that become dangerous when URL handling is sloppy: user-supplied image URLs, webhook callbacks, internal service requests, import or fetch features, and any flow where the application retrieves something on a user’s behalf. Those are exactly the kinds of places where Axios often shows up in production code. The package is not unusual for having these use cases. It is unusual for how often teams forget that they are handing a user influence over a destination, not just over a string. (OWASP 치트 시트 시리즈)
The broader lesson is simple. A client library is part of your outbound trust boundary whenever it chooses where to connect, what headers to attach, what tokens to derive from cookies, how to follow redirects, or how to interpret non-HTTP inputs. That is the lens that makes the Axios security record coherent. Without that lens, the CVEs look unrelated. With it, the pattern is obvious. (Axios)
The Axios SSRF story is really one engineering problem with multiple CVEs
Most teams first notice Axios in security feeds because of SSRF. That is reasonable, but incomplete. The Axios SSRF story is best understood as a family of failures in destination control. One record involved path-relative input unexpectedly behaving like a protocol-relative target. The next involved absolute URLs overriding a configured baseURL. In both cases, the common mistake was trusting a convenience mechanism to enforce a security property it was never designed to guarantee. (GitHub)
CVE-2024-39338 and the protocol-relative trap
GitHub’s advisory for CVE-2024-39338 states that affected Axios versions from 1.3.2 through 1.7.3 were vulnerable to SSRF because path-relative URLs could be processed as protocol-relative URLs, with 1.7.4 carrying the fix. The original report describes a common pattern: a developer creates an Axios instance with a trusted baseURL, expects to append a user-specific path, and instead gives an attacker a way to steer the request somewhere else. (GitHub)
The important part is not the exact syntax of the bad input. The important part is the assumption that “I am passing a path segment” is fundamentally weaker than “I have already canonicalized a destination and proven it is allowed.” Once user influence reaches the stage where Axios is still deciding what the real destination is, you are already closer to SSRF than most code reviewers realize. (GitHub)
CVE-2025-27152 and the absolute URL override problem
CVE-2025-27152 made the problem even easier to understand. GitHub’s advisory says that even when baseURL is set, passing an absolute URL causes Axios to send the request to that absolute target, creating a path to SSRF and credential leakage. The advisory’s example is devastatingly practical: an internal Axios client is configured with an X-API-KEY, a caller passes http://attacker.test/ instead of a relative path, and the secret-bearing request leaves for the attacker-controlled host. Patched versions are 1.8.2 그리고 0.30.0. (GitHub)
That example matters because it shows the two risks that travel together in real systems. First, you can make the server talk to somewhere it should never talk to. Second, you can leak the context that made that request privileged in the first place: API keys, bearer tokens, internal cookies, or custom headers bound to the instance. The impact is not limited to classic metadata endpoints or loopback probes. It also includes data exfiltration to an external host that simply receives the same headers your internal service would have received. (GitHub)
Why baseURL was never a policy engine
Axios’ own docs say that baseURL is prepended unless the URL is absolute, and that allowAbsoluteUrls defaults to true. That means the documented default behavior has always treated an absolute URL as authoritative. The allowAbsoluteUrls feature arrived in the 1.8.0 line, and subsequent changelog entries show more targeted fixes in 1.8.2, 1.8.3및 1.8.4 to handle path building and adapter behavior correctly. That is real progress. It is not the same thing as saying baseURL is now a complete security boundary. (Axios)
If your security model depends on “this string should stay under that base URL,” then your security model needs an explicit destination validation step before Axios sees the value. Even with newer versions, you should still treat the client library as a transport layer, not as the only place where policy is enforced. OWASP’s SSRF guidance pushes in the same direction: canonicalize the URL, validate the scheme, validate the host, and use allowlists where possible. (OWASP 치트 시트 시리즈)
Here is the pattern many applications still get wrong:
import axios from "axios";
const internalAPIClient = axios.create({
baseURL: "https://api.internal.example/v1/users/",
headers: {
"X-API-KEY": process.env.INTERNAL_API_KEY
}
});
export async function fetchUserProfile(userInput) {
// Dangerous: caller controls whether this stays a path
const res = await internalAPIClient.get(userInput);
return res.data;
}
And here is the safer version. The point is not to worship one helper function. The point is to make the destination explicit, canonical, and allowlisted before it reaches the transport layer:
import axios from "axios";
const ALLOWED_ORIGINS = new Set([
"https://api.internal.example"
]);
function buildSafePathFromUserInput(userInput) {
if (typeof userInput !== "string") {
throw new TypeError("userInput must be a string");
}
// Accept only an application identifier, not a full URL
if (!/^[A-Za-z0-9_-]+$/.test(userInput)) {
throw new Error("invalid user identifier");
}
return `/v1/users/${userInput}`;
}
function parseAndValidateWebhookURL(candidate) {
const url = new URL(candidate);
if (!["https:"].includes(url.protocol)) {
throw new Error("unsupported protocol");
}
if (url.username || url.password) {
throw new Error("embedded credentials are not allowed");
}
if (!ALLOWED_ORIGINS.has(url.origin)) {
throw new Error("destination not allowed");
}
return url;
}
const client = axios.create({
baseURL: "https://api.internal.example",
allowAbsoluteUrls: false,
headers: {
"X-API-KEY": process.env.INTERNAL_API_KEY
}
});
export async function fetchUserProfileById(userId) {
const safePath = buildSafePathFromUserInput(userId);
const res = await client.get(safePath);
return res.data;
}
export async function callTrustedWebhook(candidateURL, payload) {
const safeURL = parseAndValidateWebhookURL(candidateURL);
const res = await axios.post(safeURL.href, payload, {
headers: { "Content-Type": "application/json" }
});
return res.status;
}
This code follows the logic Node’s WHATWG URL API was designed for: parse the string into structured components and validate those components, rather than trying to infer trust from string prefixes. Node’s documentation explicitly notes the structured decomposition of a WHATWG URL object and the fact that origin includes protocol and host but not embedded credentials, which makes it a useful unit for allowlist checks. (Node.js)
The deeper lesson is that safe URL handling is not an Axios trick. It is an application design choice. You get better security when you model user input as an identifier or path segment whenever possible, and only accept full URLs in flows that genuinely require them. When you do accept full URLs, you should parse them with a standards-based URL parser, validate them against an allowlist, reject dangerous schemes, reject embedded credentials, and decide up front whether redirects and proxies are part of the trust model. (OWASP 치트 시트 시리즈)
At this point in the workflow, many teams discover that the hard part is no longer spotting the CVE. It is finding every code path where user influence reaches a destination sink, replaying controlled inputs against scoped targets, preserving evidence, and then retesting after a fix. That is exactly the stage where evidence-first offensive validation tooling becomes more valuable than another scanner alert. Penligent’s public materials describe the platform in terms that map naturally to this stage of work: recent CVE validation, one-click PoC generation, attack-surface testing, and reporting tied to reproducible evidence rather than just package metadata. (펜리전트)

CVE-2023-45857 was really about header propagation discipline
The older Axios XSRF issue is easy to misread as “just a front-end bug.” It was more important than that. GitHub’s reviewed advisory for CVE-2023-45857 says that affected versions from 0.8.1 through <0.28.0 그리고 1.0.0 through <1.6.0 could expose the XSRF-TOKEN cookie by sending X-XSRF-TOKEN in requests to unintended hosts. NVD’s wording is blunt: Axios 1.5.1 could reveal the confidential XSRF-TOKEN by including it in the X-XSRF-TOKEN header for every request made to any host. The fixes landed in 1.6.0 그리고 0.28.0. (GitHub)
What made that issue important was not only token exposure. It was the model it revealed. The client library was willing to derive a security-sensitive header from a cookie and attach it beyond the narrow trust boundary many developers assumed existed. That is the same broad category of mistake as the SSRF issues: application context escaping the boundary the programmer thought they had set. In one case it was destination choice. In this case it was header propagation. (GitHub)
Axios’ current repository documentation shows how the model changed. Today, withXSRFToken explicitly controls whether Axios reads the XSRF cookie and sets the XSRF header. The default behavior is same-origin only. The docs also note that in older Axios versions, setting withCredentials: true implicitly caused Axios to set the XSRF header for cross-origin requests, whereas newer Axios separates those concerns and requires withXSRFToken: true if you really want that behavior. (GitHub)
That change created friction for some applications, especially frameworks and backends that had silently relied on the older behavior. You can see the operational consequences in issue discussions from teams that upgraded to fix the vulnerability and then found their old CSRF flow broken. That is not a sign that the fix was wrong. It is a sign that the older behavior was doing more implicit trust propagation than many apps realized. (GitHub)
A safe migration pattern is to make the policy explicit. Do not attach a token-derived header because a request is cross-origin and happens to carry credentials. Attach it only when the destination is one you have intentionally approved for that token.
import axios from "axios";
const TRUSTED_XSRF_ORIGINS = new Set([
"https://app.example.com",
"https://api.example.com"
]);
function shouldAttachXSRFHeader(config) {
const base = config.baseURL ? new URL(config.baseURL) : new URL(window.location.origin);
const target = new URL(config.url, base);
return TRUSTED_XSRF_ORIGINS.has(target.origin);
}
const api = axios.create({
withCredentials: true,
withXSRFToken: false
});
api.interceptors.request.use((config) => {
if (shouldAttachXSRFHeader(config)) {
config.withXSRFToken = true;
}
return config;
});
The exact mechanism can vary. The important design point is that the rule lives in your code as a destination policy, not in an old library default you barely remember. That mindset scales better not just for XSRF headers, but for Authorization headers, internal API keys, tenant routing metadata, and custom headers that only make sense for one target origin. (GitHub)
Axios also has dangerous non-network paths that look harmless in review
One reason Axios security issues surprise good engineers is that they often assume all risk comes from “making an HTTP request.” That assumption breaks down in Node.js, where Axios has transport logic that can interpret more than plain HTTP URLs and can do meaningful work before any network call happens. Two recent records are especially good reminders of that. (GitHub)
CVE-2025-58754 and the data URI denial of service
The advisory for CVE-2025-58754 explains that when Axios runs on Node.js and receives a 데이터: URL, it does not perform HTTP at all. The Node adapter decodes the payload into memory and returns a synthetic response. The bug was that this path ignored maxContentLength 그리고 maxBodyLength, which only protected ordinary HTTP responses, so an attacker could hand the application a very large 데이터: URI and exhaust memory, even when the caller expected streaming semantics. Fixed versions are 0.30.2 그리고 1.12.0. (GitHub)
That issue is more than an implementation bug. It is a category lesson. If your application accepts “a URL to fetch,” the real question is not only which host it can reach. The question is also which schemes the library understands and what semantics those schemes trigger. A mental model built only around HTTP misses the possibility that an attacker can force decoding, buffering, or parsing behavior inside the client itself. (GitHub)
Here is a simplified example of how a normal-looking feature can turn into a denial-of-service sink:
import axios from "axios";
import express from "express";
const app = express();
app.get("/preview", async (req, res) => {
const target = req.query.url;
// Dangerous assumption:
// "responseType: 'stream'" does not save you from the data: URI path here
const upstream = await axios.get(target, {
responseType: "stream",
timeout: 5000,
maxContentLength: 2 * 1024 * 1024
});
upstream.data.pipe(res);
});
app.listen(3000);
만약 대상 is a giant 데이터: URI, you may not get the streaming behavior you expected. The right fix starts before Axios: reject schemes you do not need, parse the input with 새 URL(), and allow only http: 그리고 https: in routes that are supposed to perform network fetches.
function validateFetchTarget(candidate) {
const url = new URL(candidate);
if (!["http:", "https:"].includes(url.protocol)) {
throw new Error("unsupported scheme");
}
return url.href;
}
OWASP’s SSRF guidance supports the same general approach. Control the schemes, control the destinations, and do not assume that “it looks like a URL field” means every legal URL syntax should be accepted by the feature. (OWASP 치트 시트 시리즈)

CVE-2026-25639 and the mergeConfig crash
CVE-2026-25639 is another good example of a bug that reveals the wrong assumption. GitHub and NVD both describe the same condition: before 0.30.3 그리고 1.13.5, Axios’ mergeConfig function could throw a TypeError when it processed a configuration object containing __proto__ as an own property. The advisory is explicit that an attacker can trigger this using an object created via JSON.parse(), and it is equally explicit that this is not prototype pollution because the application crashes before any assignment occurs. (GitHub)
That clarification is important. Many developers see __proto__ and mentally jump straight to prototype pollution. This record is a different failure mode. It is an availability issue triggered by unsafe config ingestion. If your backend takes user-supplied JSON, parses it, and passes it straight into Axios config or into a merge that later becomes Axios config, an attacker may be able to crash request handling without ever touching a network destination. (GitHub)
Here is the brittle pattern:
import axios from "axios";
import express from "express";
const app = express();
app.use(express.json());
app.post("/proxy", async (req, res) => {
const userConfig = JSON.parse(JSON.stringify(req.body));
// Dangerous: attacker controls config shape
const response = await axios.request({
method: "GET",
url: "https://api.example.com/data",
...userConfig
});
res.json(response.data);
});
app.listen(3000);
And here is the safer one:
import axios from "axios";
import express from "express";
const app = express();
app.use(express.json());
function mapAllowedAxiosOptions(body) {
const out = {};
if (body.timeout !== undefined) {
if (!Number.isInteger(body.timeout) || body.timeout < 0 || body.timeout > 10000) {
throw new Error("invalid timeout");
}
out.timeout = body.timeout;
}
if (body.params && typeof body.params === "object" && !Array.isArray(body.params)) {
out.params = body.params;
}
if (body.headers && typeof body.headers === "object" && !Array.isArray(body.headers)) {
out.headers = {
"X-Request-Source": "proxy-service"
};
}
return out;
}
app.post("/proxy", async (req, res) => {
const safeConfig = mapAllowedAxiosOptions(req.body);
const response = await axios.request({
method: "GET",
url: "https://api.example.com/data",
...safeConfig
});
res.json(response.data);
});
app.listen(3000);
The secure design pattern here is the same as the secure URL pattern earlier: do not let user-controlled data arrive at a powerful interface in its raw form. Map it into a narrow allowlist of fields you are willing to honor, and reject the rest. The patch matters, but the coding pattern matters more. (GitHub)
Not every Axios alert means Axios itself is the broken component
One of the easiest ways to waste time in dependency response work is to treat every alert with the package name in it as a direct package defect. Axios has had a recent example that makes this mistake very obvious.
GitHub published a reviewed advisory tying [email protected] to a critical issue in [email protected], then withdrew it the next day. The withdrawal notice says users of Axios 1.10.0 had the flexibility to use a patched version of form-data without upgrading Axios, because the vulnerability originated in the transitive dependency rather than in Axios itself. The advisory had initially pointed to form-data boundary generation using Math.random() and treated [email protected] as exposed because it resolved that transitive package version. (GitHub)
That incident is useful because it teaches three operational lessons at once. First, an Axios alert may actually be a dependency-tree alert. Second, the right remediation might be a transitive override rather than a package upgrade. Third, scanner output has state, and that state matters. A withdrawn advisory should trigger a deeper look, not a reflexive mass upgrade ticket. (GitHub)
Axios’ own ecosystem gives you a practical mechanism for handling that kind of case. npm’s overrides field exists precisely to replace or pin versions of dependencies in the tree. The npm docs describe it as a way to change dependencies of dependencies, including replacing a package with a version that addresses a security issue or forcing a consistent version everywhere. (npm Docs)
A typical mitigation looks like this:
{
"dependencies": {
"axios": "1.10.0"
},
"overrides": {
"form-data": "4.0.4"
}
}
That does not mean overrides are always the best answer. It means you should distinguish between “Axios code is broken,” “Axios defaults are risky,” and “Axios pulls a bad transitive version.” Those are different problems, and mature teams respond to them differently. (GitHub)
The same caution applies to disputed records. NVD’s entry for CVE-2024-57965 explicitly includes the tag disputed and says some parties believe the change only addressed a SAST warning message rather than a true vulnerability. The record still exists. Scanners may still surface it. But the right engineering response is to read the state of the record, not just the headline. Not all dependency alerts should carry the same urgency or imply the same degree of exploitability. (NVD)
The March 2026 malicious releases changed the meaning of Axios package risk
The March 2026 Axios npm incident is the reason this topic can no longer be reduced to CVEs alone. According to the official Axios issue, versions 1.14.1 그리고 0.30.4 were compromised and removed from the registry. Microsoft’s write-up states that these versions injected a malicious dependency, [email protected], which executed a postinstall path and fetched platform-specific second-stage payloads from known attacker infrastructure. Microsoft also says the publication metadata differed from the project’s normal CI-backed publishing pattern, including missing trusted publisher binding and missing corresponding repository tag or commit trail for the malicious versions. (GitHub)
Snyk’s incident analysis reaches the same core conclusion from another angle: the Axios source code itself was not altered to add malicious runtime logic. Instead, the attacker added a purpose-built dependency whose job was to trigger install-time execution. The malicious release window was brief, but any developer workstation, CI system, or build environment that performed a fresh install during that window could have been compromised without ever importing Axios in application code. (Snyk)
That is why the registry compromise belongs in the same discussion as the CVEs even though it is not the same kind of defect. From the user’s point of view, both situations appear as “Axios security problem.” From the defender’s point of view, they require different playbooks.
| 차원 | Product vulnerability | Registry compromise |
|---|---|---|
| 근본 원인 | Bug or risky default in package behavior | Unauthorized publish path or maintainer compromise |
| Primary fix | Upgrade to patched version, review calling patterns | Treat affected hosts as potentially compromised, rotate secrets, install known-good versions |
| Investigation scope | Source usage, sinks, inputs, environment exposure | Build logs, lockfiles, hidden lockfiles, host artifacts, credentials, CI runners |
| Main question | Can attacker-controlled input trigger this path in my app | Did any environment install the malicious release during the live window |
| Good enough response | Often package upgrade plus code hardening | Often incident response, credential rotation, and host review |
Source basis for the contrast above comes from GitHub’s official Axios issue, Snyk’s incident analysis, and Microsoft’s mitigation guidance. (GitHub)
Microsoft’s guidance is appropriately blunt: organizations that installed 1.14.1 또는 0.30.4 should rotate secrets and credentials immediately and downgrade to a known-safe version such as 1.14.0 또는 0.30.3. That is not how you respond to a normal package CVE. It is how you respond when install-time malware may already have run on developer or CI infrastructure. (Microsoft)
The practical point is this: if you search for “axios npm cve” because a scanner pinged you, do not stop at patch notes. Confirm whether the alert refers to a library bug, a transitive vulnerability, a disputed record, or a compromised release. The remediation path can swing from a one-line package bump to full credential rotation and endpoint review. (GitHub)
How to verify whether your code is actually exposed
A dependency dashboard can tell you that Axios is present. It cannot tell you whether your application has turned Axios into a security boundary in the dangerous places. That takes code review and targeted validation.
The first thing to look for is any place where Axios receives attacker-influenced destination material. That includes obvious features such as webhook URLs, image download URLs, avatar import URLs, callback URLs, and generic “fetch this URL” endpoints. It also includes less obvious flows where a path segment, tenant identifier, or resource ID is assumed to be harmless even though it still influences URL construction. OWASP’s SSRF guidance is a good mental checklist because the affected business patterns look very similar. (OWASP 치트 시트 시리즈)
The second thing to look for is any place where you derive security-sensitive context automatically. If a browser flow still assumes old cross-origin XSRF behavior, or if a Node internal client attaches privileged headers to an Axios instance that can be pointed elsewhere, you have a propagation problem even if you patched the underlying CVE. The bug may be fixed, but the architectural habit remains. (GitHub)
The third thing to look for is config ingestion. Search for code that spreads, merges, or forwards request-like JSON into Axios config objects. If you find ...req.body, Object.assign(defaults, userInput), or any wrapper that accepts arbitrary config keys from outside a trust boundary, review it with CVE-2026-25639 in mind. That record is a strong reminder that configuration APIs are not harmless just because they are not your business payloads. (GitHub)
In teams that already have a mature validation workflow, this is the point where automation becomes useful in a very specific way. The hard part is not reading the advisory. The hard part is enumerating candidate sinks, replaying safe probes against scoped targets, collecting evidence, and making the retest reproducible after a fix. That is where an AI-assisted offensive workflow can be genuinely useful rather than cosmetic. Penligent’s public product positioning around evidence-first testing, CVE validation, one-click PoC generation, and reporting fits that kind of verification loop far more naturally than the older “scanner plus chatbot” model. (펜리전트)
Build evidence matters more than package.json alone
The March 2026 compromise also reminded defenders that package response is not only about source repositories. npm’s documentation on lockfiles is especially relevant here. As of npm v7, the lockfile contains enough information to describe a complete package tree, and npm also uses a hidden lockfile at node_modules/.package-lock.json to optimize installation state. If you only inspect the root package-lock.json, you may miss evidence created in local workspaces or ephemeral CI trees. (npm Docs)
That means package investigations should look at more than one layer. Review the committed lockfile, inspect any local or cached install state, and if the environment still exists, inspect the installed dependency tree. In an incident involving install-time malware, the build system’s view of what was resolved and when it was resolved can be as important as the repository’s view of declared dependencies. (npm Docs)
Here are some practical commands worth keeping around:
# Inventory direct and transitive axios versions
npm ls axios
# Search for the malicious March 2026 releases and dependency
grep -RInE 'axios@1\.14\.1|axios@0\.30\.4|plain-crypto-js' \
package-lock.json npm-shrinkwrap.json yarn.lock pnpm-lock.yaml . 2>/dev/null
# Inspect hidden npm v7+ lockfiles if node_modules still exists
find . -type f -path '*/node_modules/.package-lock.json' -print
# Check whether the suspicious dependency is present locally
find . -type d -name plain-crypto-js 2>/dev/null
Those commands are not magic, and they do not replace host review. They are just good evidence collection. The reason they matter is that npm’s install state can preserve the exact resolved tree, while the malicious Axios incident specifically abused installation behavior rather than application runtime code. (npm Docs)
Version upgrades are necessary, but they are not the whole fix
The most common dependency response mistake is treating version bumps as if they automatically erase the insecure calling pattern that made the package dangerous in context. Axios is a good example because several of its CVEs were fixed by changing how the library resolves destinations or propagates security-sensitive values. That absolutely reduces risk. It does not mean your application now has a well-defined outbound policy. (GitHub)
The safer engineering pattern is to define clear application-level rules and let Axios remain a transport tool underneath them. In practice that means modeling IDs as IDs, not as URLs; validating full URLs with the WHATWG parser before they hit Axios; separating client instances by trust domain; making header propagation explicit; rejecting dangerous schemes before the request layer; and mapping user input into narrow config allowlists instead of passing it straight through. (Node.js)
A small table makes the pattern easier to remember:
| Input shape | 일반적인 실수 | Better control |
|---|---|---|
| User ID or slug | Treated as if it cannot become a URL boundary | Validate as identifier and build the path yourself |
| Webhook URL | String prefix checks only | Parse with URL, validate scheme, origin, credentials, and port |
| Generic fetch URL | Accept all legal URL schemes | Allow only http: 그리고 https: |
| Browser XSRF token flow | Let old defaults choose header propagation | Make withXSRFToken policy explicit per trusted origin |
| User JSON config | Spread into Axios options wholesale | Map only allowed keys into a clean config object |
| Transitive package alert | Force top-level upgrade every time | Check whether override or direct transitive patching is more appropriate |
The support for these controls comes from Axios’ current config model, the relevant advisories, Node’s URL API, and npm’s override support. (Axios)
Supply chain controls are now part of the Axios security conversation
The March 2026 compromise also exposed a hard truth: you can patch every known Axios CVE and still lose if your package intake and publish controls are weak. That is not an Axios-specific observation anymore. It is a Node ecosystem observation. OWASP’s npm security cheat sheet recommends enforcing lockfiles, minimizing attack surface by ignoring run-scripts where practical, auditing dependencies, and using trusted publishers for secure package publishing. npm’s own documentation says npm ci installs from an existing lockfile and fails if the lockfile and manifest do not match, which makes it the right default for CI when you want deterministic installs rather than silent dependency drift. (OWASP 치트 시트 시리즈)
That matters because install-time attacks exploit precisely the gap between “the version I expected” and “the package I actually resolved right now.” npm ci does not solve every supply chain problem, but it closes one of the most common doors: surprise dependency graph changes during CI. OWASP’s guidance and npm’s documentation align on that point. (OWASP 치트 시트 시리즈)
The same is true for lifecycle scripts. OWASP’s npm cheat sheet specifically calls out --ignore-scripts as a way to reduce the malicious module attack surface during package installation, because install hooks such as postinstall are a known abuse path. That advice is directly relevant to the malicious Axios releases, which used an injected dependency to execute install-time code. Not every environment can globally disable scripts without breaking legitimate packages, but sensitive review pipelines and quarantine installs often should. (OWASP 치트 시트 시리즈)
For publishers, npm’s trusted publishing documentation is now central reading. npm describes trusted publishing as OIDC-based publishing from CI/CD workflows, eliminating the need for long-lived npm tokens. The docs also note automatic provenance generation and frame trusted publishing as the preferred security model over traditional tokens. That matters even more after Microsoft reported that the malicious Axios releases were published outside the project’s normal trusted-publisher-backed flow. (npm Docs)
GitHub’s provenance write-up helps explain why this is strategically important. Package provenance links a published artifact back to the repository, source commit, and build instructions that produced it. That does not stop every compromise, but it gives consumers a verifiable line from published package to source and build context, which is exactly the line defenders want when deciding whether a release looks normal or suspicious. (The GitHub Blog)
A practical Node.js dependency policy now looks less like “run audit and update monthly” and more like this:
{
"scripts": {
"deps:ci": "npm ci",
"deps:review": "npm ci --ignore-scripts"
},
"overrides": {
"axios": "1.13.5"
}
}
And in CI, the policy is often just as important as the code:
name: ci
on:
push:
pull_request:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- run: npm ci
- run: npm test
That is not a full supply chain program, but it captures the key idea: freeze what you can, review what you install, and make publishing and artifact lineage harder to subvert. The Axios incident turned that from a nice-to-have into a mainstream expectation. (npm Docs)

What teams should do now
If you need one operational decision tree, it should start with classification. If the issue is CVE-2024-39338 or CVE-2025-27152, you should patch and then review every place where attacker-controlled input can influence a request destination. If the issue is CVE-2023-45857, patch and then review where security-sensitive headers are derived and where they are allowed to travel. If the issue is CVE-2025-58754, patch and then reject non-HTTP schemes before the request layer. If the issue is CVE-2026-25639, patch and then stop accepting arbitrary config-shaped objects from outside your trust boundary. (GitHub)
If the issue is [email protected] 또는 0.30.4, do not treat it as ordinary dependency maintenance. Treat any environment that installed those versions as potentially compromised, rotate secrets, inspect build and install evidence, and move to a known-safe version. That is the clear line in Microsoft’s guidance and in the broader incident reporting from the security community. (Microsoft)
If the alert is disputed or withdrawn, do not ignore it blindly and do not escalate it blindly. Read the state of the record. Determine whether the problem is direct, transitive, theoretical, disputed, or withdrawn. Good dependency response is not about always moving faster. It is about classifying correctly so you do not waste time fixing the wrong thing while missing the real boundary failure. (GitHub)
Further reading and reference links
For the official package-side view, the Axios GitHub security advisories page is the best starting point, especially for the currently published advisories and their affected and patched version ranges. (GitHub)
For the SSRF records, read the GitHub advisory and NVD entry for CVE-2024-39338, then the GitHub advisory and NVD entry for CVE-2025-27152. Together they show the evolution from protocol-relative confusion to absolute-URL override, which is the clearest way to understand the Axios destination-control problem. (GitHub)
For the browser-side token issue, the GitHub advisory and NVD entry for CVE-2023-45857 remain the authoritative references, and Axios’ current repository documentation on withXSRFToken is useful for understanding how the model changed after the fix. (GitHub)
For the Node-specific denial-of-service paths, read the advisory and NVD entry for CVE-2025-58754 and the advisory plus release information for CVE-2026-25639. Those two records are the strongest evidence that Axios security review should include non-network paths and config ingestion paths, not just SSRF sinks. (GitHub)
For defensive engineering, OWASP’s SSRF Prevention Cheat Sheet, the npm security cheat sheet, npm’s docs for package-lock.json, npm ci, overrides, and trusted publishing are more useful than most secondary blog posts because they translate dependency events into durable controls. (OWASP 치트 시트 시리즈)
For the March 2026 malicious release incident, Microsoft’s mitigation write-up is the most useful operational reference, especially for the host-compromise mindset, safe downgrade guidance, and the note that the malicious publication differed from the project’s normal trusted-publisher pattern. Snyk’s incident analysis is also valuable for understanding the install-time dependency injection path. (Microsoft)
For related Penligent reading, the most directly relevant internal article is Axios Compromised on npm, What the Malicious Releases Actually Did, which complements this piece by focusing on the malicious release mechanics rather than the longer-term Axios boundary model. Penligent’s public product pages are also relevant if your next step is turning these review patterns into scoped, repeatable validation and evidence collection rather than leaving them as checklist items. (펜리전트)

