redos-db › cross-spawn-CVE-2024-21538

cross-spawn CVE-2024-21538

Real-world ReDoS: quadratic (n²) catastrophic backtracking

quadraticCVEjavascript

cross-spawn is one of the most-downloaded packages on npm (a transitive dependency of countless CLIs and build tools via its use inside `execa` and many others). When escaping command arguments for Windows in `lib/util/escape.js`, it doubled trailing backslashes with the regex `/(\*)$/`. Because `(\*)` greedily matches a run of backslashes and the pattern is not anchored at the start of the string, an argument consisting of a long run of backslash characters forces the engine to greedily consume the run, fail the `$` anchor, backtrack one backslash at a time, and then retry the whole match from each successive start offset: quadratic O(n^2) blow-up. Since argument strings can be attacker-influenced, this is a denial-of-service vector. cross-spawn 7.0.5 (and 6.0.6) replaced the greedy group with a backtracking-free lookahead `/(?=(\+?)?)\1$/`.

Vulnerable regex

(\\*)$

Attack

Input that triggers the blow-up: a run of "\\" then "!". A benign input like \\\\ matches in microseconds.

Details

CVECVE-2024-21538
GHSAGHSA-3xgq-45jj-v275
WeaknessCWE-1333 (Inefficient Regular Expression Complexity)
Packagecross-spawn (npm)
Affected>=7.0.0 <7.0.5 || <6.0.6
Patched in7.0.5
Published2024-11-08
Discovered byreported via GitHub advisory GHSA-3xgq-45jj-v275
Complexityquadratic (n²)

The fix

cross-spawn's Windows argument escaper in `lib/util/escape.js` doubled trailing backslashes with `arg.replace(/(\*)$/, '$1$1')` (and doubled backslashes before a quote with `/(\*)"/g`). The group `(\*)` greedily consumes a run of backslashes and, because the overall match is not anchored at the start, the engine retries the greedy-then-backtrack of `$` from every offset in the run: O(n^2) on a long backslash run that never satisfies the anchor. cross-spawn 7.0.5 / 6.0.6 rewrote both patterns to a lookahead form `/(?=(\+?)?)\1$/` that captures the run without a backtrackable greedy quantifier, making the scan linear.

fix type: regex-rewrite

Fix commit: https://github.com/moxystudio/node-cross-spawn/commit/5ff3a07d9add449021d806e45c4168203aa833ff

Measured blow-up

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
25019.8 ms
500138.9 ms
10001154.0 ms
20001617.8 ms
▶ Watch it melt down Scan your own code for ReDoS ← All ReDoS entries

References

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.