ReDoS Checker (Catastrophic Backtracking Detector)
A single badly-written regular expression can freeze a server. Patterns like (a+)+$ take exponentially longer to fail as the input grows — feed one a few dozen non-matching characters and the match can run for minutes. That is a ReDoS (Regular expression Denial of Service). This tool checks a pattern two ways: it statically detects the structures that cause catastrophic backtracking, and it actually measures how match time grows against a hostile input in your own browser, so you get real numbers, not just a warning.
How to use the ReDoS Checker (Catastrophic Backtracking Detector)
Paste the pattern into the Regular expression box. You can enter just the pattern body ((a+)+$) or a full JavaScript literal (/(a+)+$/i) — the tool strips the slashes and reads the flags for you. Add flags such as i or m in the second box if you are not using literal syntax. Click Check for ReDoS.
You get two panels. The first is the static verdict: the tool parses your pattern into a small syntax tree and looks for the three shapes that cause catastrophic backtracking — a nested unbounded quantifier such as (a+)+, an overlapping alternation under a quantifier such as (a|ab)*, and two adjacent quantifiers over the same characters such as \d+\d+. Each finding names the danger and gives a concrete fix.
The second panel is the live timing probe. The tool builds the worst-case input for your pattern — a run of matching characters followed by a character that forces the match to fail — and measures how long the match takes at growing input lengths, right in your browser. A safe pattern stays flat. A vulnerable one climbs steeply, and the probe aborts the moment a single match crosses 750 ms so it can never hang your tab. Everything runs locally; your pattern is never sent anywhere.
What is ReDoS and catastrophic backtracking?
Most regex engines in mainstream languages — JavaScript, Python's re, Java, Ruby, PHP's PCRE, .NET — use a backtracking matcher. When a pattern can match a piece of input in more than one way, the engine tries one option, and if the overall match later fails, it backs up and tries another. For most patterns that is cheap. For a few structural shapes the number of ways to split the input grows exponentially with input length, and the engine tries all of them before giving up. That is catastrophic backtracking, and when an attacker can supply the input, it becomes a denial-of-service vulnerability: ReDoS.
The canonical example is (a+)+$. The inner a+ can match one or more as, and the outer + repeats that, so for an input of n as there are 2n-1 ways to partition them between the two quantifiers. Against "aaaaaaaaaaaaaaaaaaaaaaaaX" the match must fail — there is no X allowed before end-of-string — so the engine explores every one of those partitions first. Twenty-five characters already takes seconds; forty would take longer than the universe has existed. The three structural culprits this tool detects are:
- Nested quantifiers — an unbounded quantifier wrapping a group that also has an unbounded quantifier:
(a+)+,(a*)*,([a-z]+)*,(\w+\s?)*. Exponential. - Overlapping alternation under a quantifier — branches that can match the same character:
(a|a)*,(a|ab)*,(\w|\d)+. Exponential. - Adjacent overlapping quantifiers — two repeats over the same character set in sequence:
\d+\d+,.*.*,\s*\s*. Usually polynomial (quadratic) rather than exponential, but still enough to stall on a long input.
Note that a truly linear engine — Go's RE2, Rust's regex crate, or the non-backtracking option in .NET — cannot suffer ReDoS at all, because it never backtracks. If you control the runtime and the patterns are static, switching engines is the most complete fix. When you cannot switch, the practical defences are: bound every quantifier ({1,64} instead of +), use atomic groups (?>...) or possessive quantifiers a++ to stop the engine reconsidering a run it already consumed, make alternation branches mutually exclusive, and never interpolate untrusted text into a pattern without escaping it.
Common use cases
- Reviewing a pull request. A new validation regex lands in a diff. Paste it here before approving — nested quantifiers hide easily in an innocent-looking email or URL validator.
- Auditing a dependency. A CVE mentions a ReDoS in a library's regex. Drop the reported pattern in to see the timing curve and confirm the severity for your own input sizes.
- Hardening user-facing search or filters. Any feature that compiles a regex from user input, or matches user input against a server-side pattern, is a ReDoS target. Test the pattern against the shape an attacker would send.
- Learning why a pattern is slow. If a log-parsing or scraping job occasionally hangs on certain lines, the timing probe shows whether the regex is the cause and which structure to rewrite.