Axios: ReDoS in fromDataURI data: URL parser freezes the Node event loop (DoS)GHSA-c29m-xwm3-cm6r
Fix: axios/axios#11141GHSA-c29m-xwm3-cm6r is a CWE-1333 vulnerability in axios. A fix is available for axios — see the affected versions and patch details below.
Exploitation Status
Proof-of-concept exploit code exists
- CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.
Exploitation and automatability from CISA’s SSVC triage for GHSA-c29m-xwm3-cm6r.
EPSS Exploitation Probability
Probability of exploitation in the next 30 days, from FIRST.org EPSS.
Real-World Exposure
How broadly this vulnerability is actually deployed: weekly install volume shows current usage, and reverse-dependency count shows how many other packages break if it stays unpatched.
axiosnpmDescription
Summary
Axios for Node.js parses data: URLs in lib/helpers/fromDataURI.js. The current RFC-2397 parser uses a regular expression whose media type groups allow / inside both sides of the type/subtype match. A malformed data: URL containing many slashes and no comma forces the JavaScript regex engine to try many possible placements for the separator before failing.
Applications are affected when they pass untrusted URL strings to axios and do not reject or constrain data: URLs before axios parses them.
Impact
An attacker can make the Node.js event loop spend significant synchronous CPU time parsing a single malformed URL. In a server that accepts a URL from an HTTP request and calls axios.get(url), this can block unrelated requests and health checks until parsing completes.
The issue is availability-only. It does not disclose data or modify requests.
Affected Functionality
Affected:
- Node.js HTTP adapter data URL handling.
axios.get()or equivalent calls whereconfig.urlhas thedata:protocol.
Not affected:
- Browser fetch/XHR URL handling.
- Node requests where the application rejects
data:URLs before calling axios. - Older checked
0.xdata URL parser shape unless separately proven vulnerable.
Technical Details
lib/helpers/fromDataURI.js contains:
const DATA_URL_PATTERN = /^([^,;]+\/[^,;]+)?((?:;[^,;=]+=[^,;]+)*)(;base64)?,([\s\S]*)$/;
The [^,;]+ groups include /, so a long string of slashes without a comma can be partitioned around the required \/ in many ways before the match fails. The match runs before axios can apply request timeout behavior, so timeout does not mitigate the parsing pause.
Local timing on axios 1.18.1 with small payloads showed about 2.4 ms at 1000 slashes, 16.6 ms at 3000 slashes, and 71.5 ms at 6000 slashes, consistent with the submitted quadratic scaling while avoiding long-running payloads.
Proof of Concept of Attack
Constrained helper-level demonstration:
import axios from 'axios';
await axios.get('data:' + '/'.repeat(6000));
The request fails after parsing, but the failure is delayed by synchronous regex work. Larger payloads increase the pause substantially.
Workarounds
Reject data: URLs before passing untrusted input to axios, or enforce a strict maximum URL length for URL-fetching endpoints. Applications that do not need data: URL support should deny that protocol explicitly.
ReDoS in fromDataURI data: URL parser freezes the event loop (DoS)
Affected
- Package:
axios(Node.js http adapter) - Versions: 1.x (regex present on
v1.x, current release line) - File:
lib/helpers/fromDataURI.js - CWE-1333 (Inefficient Regular Expression Complexity)
Issue
fromDataURI parses data: URLs with this regex:
// lib/helpers/fromDataURI.js:9
const DATA_URL_PATTERN = /^([^,;]+\/[^,;]+)?((?:;[^,;=]+=[^,;]+)*)(;base64)?,([\s\S]*)$/;
The mediatype tokens [^,;]+ include /, so they can span multiple slashes ambiguously. A data: URL made of many slashes with no comma forces the engine to try every way to place the single \/ divider before failing — quadratic O(n²) backtracking. It runs synchronously on the main thread, so the whole Node event loop is frozen for the entire parse. Reachable through the public API on the Node http adapter (axios.get(url)); the browser fetch/xhr adapters are not affected because they do not call fromDataURI.
A configured timeout does not help: the freeze happens during parsing, before any network timer can fire.
PoC (minimal)
import axios from 'axios';
// ~256 KB data: URL of pure slashes, no comma
await axios.get('data:' + '/'.repeat(262139)); // blocks the event loop ~6 min, then throws
Lab results
Single-threaded "fetch a user-supplied URL" service (link-preview style) calling axios.get on a JSON body { "url": "..." }, with timeout: 1000 set.
Scaling is clean O(n²) (constant k ≈ 5.6e-6 ms/byte², stable across sizes):
| data: URL size | Event-loop freeze (one request) |
|---|---|
| 32 KB | 6.3 s (measured end-to-end; server logged event loop BLOCKED for 6.30s) |
| 64 KB | ~24 s |
| 128 KB | ~96 s |
| 256 KB | ~385 s (~6.4 min) |
| 1 MB | ~100 min |
During the freeze the server answers nothing: a /healthz liveness probe times out for the whole window, and the server's own event-loop monitor cannot even log until the parse finishes. In a run through an intercepting proxy, the proxy hit its 120 s upstream timeout and gave up, while the origin stayed pegged at 100% CPU on one core past that — client/proxy timeouts do not mitigate it.
The attacker controls only the URL string and needs no auth. ~256 KB every ~6 min (≈ 0.7 bytes/sec) keeps a server permanently unavailable.
Impact
Unauthenticated remote denial of service. One small request takes a Node service fully offline for minutes; a trickle keeps it down indefinitely.
CVSS 3.1: 7.5 (High) — AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H.
Fix
RFC 2045 type/subtype tokens never contain /. Excluding / from those two character classes removes the ambiguity and the backtracking:
const DATA_URL_PATTERN = /^([^,;/]+\/[^,;/]+)?((?:;[^,;=]+=[^,;]+)*)(;base64)?,([\s\S]*)$/;
Worst-case parse drops from ~2600 ms to ~0.002 ms. All valid data: URLs, including slashes in the body, parse identically.
Affected Packages
| Ecosystem | Package | Vulnerable range | Fix |
|---|---|---|---|
| 📦npm | axios | ≥ 1.16.1&&< 1.20.0 | 1.20.0npm install axios@1.20.0 |
Detection & mitigation playbook
Open-source dependencyDetect
Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for axios, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.
Fix
Update axios to 1.20.0 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms GHSA-c29m-xwm3-cm6r is resolved across your whole dependency graph.
Workarounds
Cap what an attacker can consume: apply request size, rate and timeout limits in front of the affected component, and run it with memory and CPU limits so exhaustion degrades one worker rather than the whole service.
Fixing This On Your OS
If you run this on a Linux distribution, patch through your package manager against the distro's own security advisory below — it tracks the exact backported fix for your release, which can ship on a different timeline (and sometimes a different severity) than the upstream project.
| Product | Fixed in | Advisory |
|---|---|---|
| Red Hat Hardened Images | grafana13-1-main-13.1.6-0.6.hum1 | RHSA-2026:74869 |
| Red Hat Hardened Images | grafana12-4-main-12.4.12-0.3.hum1 | RHSA-2026:74871 |
| Red Hat Hardened Images | grafana13-2-main-13.2.1-0.9.hum1 | RHSA-2026:74872 |
Frequently Asked Questions
Is GHSA-c29m-xwm3-cm6r in your dependencies?
Find it across npm, including transitive dependencies.