ReDoS Checker

Find catastrophic backtracking, then prove it by measurement

Analyze a Pattern

Type the pattern exactly as your engine sees it. Delimiters such as / are not part of the pattern.

Flags

What this measures

Static analysis flags pattern shapes that are known to backtrack badly. It cannot prove a pattern is safe. So this tool also measures: it feeds the pattern strings of growing length into a real RegExp and records the wall-clock time at each size.

It then fits the cost factor k, where time is proportional to length raised to k. Linear matching gives k near 1, a quadratic gives k near 2, and an exponential pattern has no fixed k at all: k climbs at every rung because each extra character multiplies the work. The table below is the evidence; the static findings are the explanation.

The measurement runs in a Web Worker

A catastrophic pattern freezes the thread that runs it. This page runs every timing loop inside a Worker built from a Blob URL, and terminates the worker when a single trial exceeds the budget. The interface therefore stays responsive while a hostile pattern is being measured, which is the whole reason this is not just a pattern-matching exercise.

Which engines can actually be attacked

EngineRuntime cost
RegExp (V8, JavaScriptCore, SpiderMonkey)Backtracking, vulnerable
PCRE / PCRE2 (PHP, many proxies)Backtracking, vulnerable
Python reBacktracking, vulnerable
Java java.util.regex, .NET, PHP preg_*Backtracking, vulnerable
RE2 / Go regexp / Rust regexLinear time, not vulnerable

Switch the target engine to Non-backtracking and the page stops claiming a pattern is dangerous, because on RE2 the same pattern has a guaranteed linear time bound. It still reports that backreferences and lookarounds are unsupported there, since those are the constructs that make people reach for a backtracking engine in the first place.

The four shapes this looks for

  • Nested quantifiers — a quantified group whose body is itself quantified, such as (a+)+ or (\w+\s?)*. The inner and outer repetition can divide the same input in exponentially many ways.
  • Quantified alternation with overlapping branches — (a|a?)+ or (a|aa)+, where more than one branch can consume the same character.
  • Adjacent quantifiers over overlapping character sets — .*.*, \w+\w*, [a-z]+[a-z]+. This is the shape behind the 2 July 2019 Cloudflare outage, where .*.*=.* in a WAF rule exhausted CPU.
  • Quantifier over a group that can match empty — (a?)+. The group succeeds without consuming anything, so the engine can retry the outer loop forever on the same position.

What it will not tell you

A clean report means no known-vulnerable shape was found and no blow-up was measured up to the tested length. It is not a proof of safety. Engines differ in which constructs backtrack and in how they optimise, a pattern can be linear on short inputs and exponential on inputs longer than anything tested here, and the attack string is generated from the pattern's own character set rather than solved for, so it is a demonstration rather than a minimal payload.

Frequently Asked Questions

What is ReDoS?Regular expression denial of service: an attacker sends a short, crafted string that forces a backtracking engine to explore an enormous number of ways to match it, pinning a CPU core for far longer than the request should take. Tracked as CWE-1333, Inefficient Regular Expression Complexity.
How long is an attack string?Usually far shorter than people expect. For a pattern like ^(a+)+$ the number of ways to split the input into groups roughly doubles per character, so a few dozen characters are enough to make matching take minutes.
Does my data leave the browser?No. Parsing, static analysis and the timing loop all run on this page. The worker is created from a Blob URL held in memory and is never uploaded anywhere.
Why does it say a RE2 pattern is safe?RE2, Go's regexp and Rust's regex simulate all possible states at once instead of retrying alternatives, which gives a guaranteed linear time bound. ReDoS is a property of the engine, not only of the pattern.
How do I fix a vulnerable pattern?Start from the suggested rewrite in the report, then re-run the checker. The checker cannot verify that a rewrite is semantically equivalent, so confirm the rewrite against your own test cases.
Is this the same as regex testing?No. Use the Regex Tester to see what a pattern matches. Use this page to find out what a pattern costs when a match fails.
Created: 2026-10-08

Comments & Ratings

Be the first to comment.

References