redos-db › debug-CVE-2017-16137

debug CVE-2017-16137

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

quadraticCVEjavascript

debug is one of the most-downloaded packages in the entire npm ecosystem (a transitive dependency of Express, Mocha, and thousands of other tools). When a debug statement logs an object with the `%o` or `%O` formatter, the formatter runs `util.inspect()` and then collapses the resulting multi-line string with the regex `/\s*\n\s*/g`. Because the whitespace groups on both sides of the newline overlap, a value whose inspected form contains a long whitespace run without a newline forces quadratic backtracking, letting attacker-controlled logged data stall the event loop. (The same bug is also tracked as CVE-2017-20165 / GHSA-9vvw-cc9w-f27h.)

Vulnerable regex

\s*\n\s* (flags: g)

Attack

Input that triggers the blow-up: a run of " ". A benign input like foo bar baz matches in microseconds.

Details

CVECVE-2017-16137
GHSAGHSA-gxpj-cx7g-858c
WeaknessCWE-1333 (Inefficient Regular Expression Complexity)
Packagedebug (npm)
Affected<2.6.9 || >=3.0.0 <3.1.0 || >=3.2.0 <3.2.7 || >=4.0.0 <4.3.1
Patched in3.1.0
Published2018-06-07
Discovered byCristian-Alexandru Staicu et al. (reported via Node Security)
Complexityquadratic (n²)

The fix

debug's `%o`/`%O` object formatter normalized the multi-line output of `util.inspect()` by collapsing newline-surrounding whitespace with `str.replace(/\s*\n\s*/g, ' ')`. The two greedy `\s*` groups on either side of `\n` overlap: on a long run of whitespace that contains no newline, at every start offset the leading `\s*` matches to the end of the run and then fails to find the required `\n`, and the global search retries from the next offset, giving O(n^2) behaviour on attacker-influenced logged objects. debug 3.1.0 (commit c38a016) removed the regex entirely and replaced it with a linear `inspected.split('\n').map(str => str.trim()).join(' ')`, producing the same normalization without backtracking.

fix type: algorithm-change

Fix commit: https://github.com/debug-js/debug/commit/c38a0166c266a679c8de012d4eaccec3f944e685

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.09 ms); the empirical complexity (quadratic) must match the declared label or the build fails.

input length (chars)match time
25007.5 ms
500029.1 ms
10000116.9 ms
20000465.5 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.