TL;DR
ReDoS (Regular Expression Denial of Service) happens when a regex pattern takes exponentially longer to process certain inputs. Attackers send a crafted string, and your regex runs for minutes or hours, freezing the Node.js event loop the whole time. Avoid nested quantifiers, and test your regexes with tools like safe-regex.
How ReDoS Works
Some regex patterns have "catastrophic backtracking": the engine tries every possible way to match before it gives up. Add one more character and the processing time doubles. It adds up fast.
// Evil pattern: nested quantifiers
const emailRegex = /^([a-zA-Z0-9]+)+@/;
// Normal input: "user@example.com" - fast
// Attack input: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!" - SLOW!
// The regex tries every way to split the "a"s
// 30 characters = 2^30 combinations = ~1 billion tries
Node.js warning: JavaScript runs on a single thread, so while the regex is chewing through input, nothing else runs. One ReDoS attack can freeze your entire server.
Dangerous Patterns
Email and URL validators are the usual home for these, since both invite nested groups.
- Nested quantifiers:
(a+)+,(a*)*,(a+)* - Overlapping alternations:
(a|a)+ - Groups with repetition:
([a-zA-Z]+)*
How to Prevent ReDoS
// Use atomic groups or possessive quantifiers (if supported)
// Or rewrite the pattern
// Dangerous
const bad = /^([a-zA-Z0-9]+)+$/;
// Safe alternative
const good = /^[a-zA-Z0-9]+$/;
// Or use a library
import validator from 'validator';
validator.isEmail(input); // Pre-tested, safe patterns
How do I test my regexes?
Try tools like safe-regex, rxxr2, or regex-static-analysis. You can also test by hand: throw a string like "aaaaaaaaaaaaaaaaaaaaa!" at it and watch whether it hangs.
Should I avoid regex entirely?
No. Just watch user-controlled input closely, lean on battle-tested libraries for common patterns like emails and URLs, and cap input length before it reaches your regex.
Scan for ReDoS Patterns
Our scanner identifies dangerous regex patterns in your code.