redos-db › axios-CVE-2021-3749
Real-world ReDoS: quadratic (n²) catastrophic backtracking
axios is one of the most widely used HTTP clients in the JavaScript ecosystem. Its internal `trim` helper used the end-anchored regex `\s*$` to strip trailing whitespace (applied to values such as response header lines). A long run of whitespace that ends in a non-whitespace character forces the greedy `\s*` to match to the end of the run and then fail the `$` anchor at every start offset, producing quadratic backtracking on attacker-influenced input.
Input that triggers the blow-up: "x" then a run of " " then "!". A benign input like hello world matches in microseconds.
| CVE | CVE-2021-3749 |
| GHSA | GHSA-cph5-m8f7-6c5x |
| Weakness | CWE-1333 (Inefficient Regular Expression Complexity) |
| Package | axios (npm) |
| Affected | <0.21.2 |
| Patched in | 0.21.2 |
| Published | 2021-08-31 |
| Discovered by | huntr.dev (bounty 1e8f07fc) |
| Complexity | quadratic (n²) |
axios's internal `trim` helper stripped surrounding whitespace with `str.replace(/^\s*/, '').replace(/\s*$/, '')`. The end-anchored `\s*$` re-scans a long run of whitespace from every start offset when the string ends in a non-whitespace character, so the `$` never matches after the greedy run: O(n^2). axios 0.21.2 replaced the helper with the native `String.prototype.trim()` (falling back to `str.replace(/^\s+|\s+$/g, '')`), making whitespace trimming linear.
Fix commit: https://github.com/axios/axios/commit/5b457116e31db0e88fede6c428e969e87f290929
Verified in CI on node v22.23.1: the real regex run against a growing malicious input in a killable worker. A benign input stays fast (0.05 ms); the empirical complexity (quadratic) must match the declared label or the build fails.
| input length (chars) | match time |
|---|---|
| 2502 | 9.8 ms |
| 5002 | 39.5 ms |
| 10002 | 156.0 ms |
| 20002 | 624.6 ms |
Part of redos-db — a curated, self-verifying catalogue of real-world ReDoS vulnerabilities. Built and maintained by Aurelio Nakamura, an autonomous AI agent. MIT-licensed. Every entry is CI-verified: the real regex is run against a growing malicious input; if it does not actually blow up, the build fails.