1001Ferramentas
🐌 Security

Regex ReDoS Risk Analyzer

Analyzes a regular expression and flags ReDoS-prone parts, such as nested quantifiers and ambiguous alternation, without running it.

Paste the bare body or the literal form /^(a+)+$/gi — the flags are split out on their own.

The analysis is static: your expression is compiled to check the syntax and then read character by character. It is never run against generated input, and nothing you type leaves the browser.

Why backtracking explodes

JavaScript, Java, Python and PCRE use a backtracking engine: when a branch fails, it rewinds and tries the next split of the same text. In ^(a+)+$ against thirty letters a followed by an exclamation mark, the engine has to try every way of cutting those letters into groups before it can say no, and the count doubles with each extra letter.

The check here is heuristic and reads the shape of the expression, not its behaviour: an empty report is not proof that the expression is safe, and a finding is not proof that it can be exploited in your context. Anchoring, capping repetition with {0,50} and rejecting oversized input before the match are the fixes that survive a rewrite.

Where a regex stalls on short input

ReDoS is the freeze that shows up when a regular expression has to try an absurd number of paths before deciding that the text does not match. The analysis here is static: the expression is compiled only to check its syntax and then read character by character, marking suspect stretches by position. Nothing runs against generated input, so the tab is in no danger of locking up during the check.

The textbook case is ^(a+)+$. Against thirty letters a followed by an exclamation mark, the engine has to try every way of splitting those thirty letters between the two repetitions before it can answer no, and each extra letter doubles the count. Alternations such as (a|ab)* fall into the same hole, because both branches start with the same character and the engine cannot tell which one to use at each position.

The part that usually escapes notice is that anchoring with ^ and $ helps but does not cure: the anchor cuts the attempts at different starting positions and changes nothing inside the nested group. The fixes that survive a review are capping repetition with {1,50}, making alternation branches mutually exclusive, rejecting input above a size limit before the regex runs, and giving heavy validation a timeout.

Frequently asked questions

Does the tool run my expression?
Only the new RegExp constructor runs, and only to learn whether the syntax is valid and the flags exist. Compiling does not make the engine search any text. The suggested attack string comes out as code for you to paste into a benchmark with a timeout, in a process you can kill, and it should not be pasted back into the field on this page.
Does an empty report mean the regex is safe?
No. The check reads the shape of the expression and recognises the known backtracking patterns, so unusual constructs, backreferences and interactions between distant groups can slip through without raising anything. Treat a clean report as absence of signal rather than approval, and keep an input size limit even on expressions that look calm.
Can I fix it without rewriting the expression?
Usually yes. Trimming the input to a maximum length before the match already drops the cost, because the blowup depends on the length of the text. Backtracking-free engines such as RE2 and the node-re2 package settle it for good, at the price of lookarounds and backreferences. In Java you can run the match on a thread with a deadline; in Node, on a worker you can terminate.

Related Tools