redos-db › ms-CVE-2015-8315

ms (millisecond duration parser) CVE-2015-8315

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

quadraticCVEjavascript

ms is one of the most-downloaded npm packages ever (a transitive dependency of debug, express and much of the ecosystem). Its string parser turns human durations like `2 days` or `100ms` into milliseconds. The leading `(?:\d+)?\.?\d+` lets a run of digits be split ambiguously between the optional `(?:\d+)?` group and the mandatory `\d+`; when the string is a long digit run followed by a character the unit alternation and end-anchor reject, the engine retries every split, giving quadratic-time backtracking. Any code that passes an untrusted string to ms() (parsing a config value, a header, a query parameter) can be stalled.

Vulnerable regex

^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$ (flags: i)

Attack

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

Details

CVECVE-2015-8315
GHSAGHSA-3fx5-fwvr-xrjg
WeaknessCWE-1333 (Inefficient Regular Expression Complexity)
Packagems (npm)
Affected<0.7.1
Patched in0.7.1
Published2016-04-20
Discovered byAdam Baldwin (@evilpacket)
Complexityquadratic (n²)

The fix

The vulnerable regex was NOT changed. ms 0.7.1 added a single input-length guard at the top of parse(): `str = '' + str; if (str.length > 10000) return;`. This caps how far the quadratic backtracking can run rather than removing it — a string of exactly 10000 digits can still take ~1s. Later releases (0.7.3 lowered the cap to 100 chars) tightened the bound further, but the underlying regex ambiguity `(?:\d+)?\.?\d+` remains. A useful lesson: many real-world ReDoS 'fixes' are input-size caps, not regex rewrites.

fix type: input-limit

Fix commit: https://github.com/vercel/ms/commit/48701f029417faf65e6f5e0b61a3cebe5436b07b

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

input length (chars)match time
250251.7 ms
5002208.0 ms
10002837.2 ms
20002timed out
▶ 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.