by RegexProof (LX AI)
Nested quantifiers like (a+)+ and overlapping alternations are classic ReDoS shapes. When user input is untrusted, prefer engines or constructs that bound backtracking, and fail closed on patterns you cannot explain. OWASP documents the attack class; your job is to keep those shapes out of request paths.
Regular-expression Denial of Service happens when a crafted input forces the matcher into catastrophic backtracking. CPU spikes, request latency explodes, and a single endpoint can starve the process. This is not theoretical trivia: any regex on an HTTP boundary, log line, or upload name is a candidate if it uses risky repetition.
I start from the OWASP ReDoS page and then map it to our routes (OWASP ReDoS). The heuristic pass is intentionally boring: find nested quantifiers, overlapping alternation, and ambiguous repetition on large input fields.
Nested quantifiers such as (a+)+, (a*)*, or (a+)* are the textbook form. Overlapping alternation like (a|a)+ or more subtle shared prefixes create the same explosion. Optional groups wrapped in outer repetition are easy to miss in review because they look tidy.
Also flag patterns that mix greedy repetition with a trailing condition that often fails, because the engine walks huge trees before rejecting. If you cannot sketch why the match is linear, treat it as guilty until proven otherwise.
.* or .+ before a failing literal on long stringsRegexProof calls out risky repetition when it explains a forge. That is a first pass, not a proof of safety under every input.
Some deployments move hot validators to engines designed to avoid catastrophic backtracking (RE2-style guarantees). That is an architecture control, not a regex tweak. If you stay on backtracking engines such as typical ECMAScript RegExp or PCRE, you own the pattern review. Read the dialect you actually run: ECMA-262 RegExp for JavaScript, PCRE for many gateways.
| Control | What it buys you | What it does not buy |
|---|---|---|
| Input length cap | Bounds worst-case work | Correctness of the pattern |
Heuristic lint for nested +/* | Catches common shapes | Novel slow patterns |
| Timed unit tests | Regression signal in CI | Proof against all adversaries |
| Non-backtracking engine | Removes a whole class of risk | Feature parity with PCRE toys |
| Human review of LLM output | Stops stacked quantifiers early | A guarantee of perfection |
Rewrite when the pattern is readable as a small state machine or string library calls. Relocate when you need rich matching but can put it off the request thread with strict timeouts. Keep only when fixtures stay fast on long near-miss inputs and an owner accepts residual risk in writing.
These heuristics are not a formal proof, not a guarantee that RegexProof finds every dangerous pattern, and not a substitute for input caps and timeouts. We do not publish invented breach counts or “100% detection” claims. Use the checklist to prioritize review; keep OWASP and your engine docs open when you argue about a specific shape.
A ReDoS review that only uses short happy-path strings will always look fine. I keep a folder of near-miss inputs: long runs of the repeated character the pattern loves, then a failing trailer. The test fails if matching exceeds a small millisecond budget on the CI runner we actually use.
If the team cannot agree on a budget, start with a conservative cap and tighten once you have baselines. The point is a regression signal, not a scientific paper. Pair the timed test with an input length limit so production never sees megabyte-scale toys.
Many “clever” validators are clearer as split/join, URL parsers, or small hand parsers. Boring code has linear behavior you can read. I move structured formats (UUIDs, dates with fixed shapes, simple tokens) away from regex when the pattern starts collecting stars.
Regex still wins for light lexing. The honesty rule is simple: if you cannot explain the worst-case growth, do not put it on the request path.
Models like stacked quantifiers because they look precise. Treat every forge as untrusted until the heuristic checklist and timed fixtures pass. RegexProof’s edge-case callouts are a starting filter. Your CI budget and input caps are the controls that keep the site up.
When writing status updates for stakeholders, say what you measured (fixture time, input cap) instead of claiming complete protection. Overclaiming creates support debt when the next novel pattern appears.
I refuse status language that says a tool never misses dialect bugs or ReDoS shapes. The honest line is: we run fixtures in the production engine, we cap input length, and we review nested quantifiers. Residual risk stays owned by a named person.
That stance keeps blog posts aligned with what RegexProof actually sells — a forge with explanations and edge-case flags — instead of a mythical perfect scanner. Readers who need formal assurance still need their own security review.
When you teach a junior teammate, have them break a pattern on purpose with a long near-miss string. Watching CPU climb teaches faster than another abstract warning. Then fix the pattern and keep the failing fixture in CI so the lesson sticks.
Finally, keep primary sources bookmarked: ECMA-262 for JavaScript RegExp behavior, PCRE docs for gateway rules, and OWASP for the ReDoS threat model. Tools help; the contract still lives in those references.
Flag nested quantifiers and overlapping alternation first, cap input length, and time your fixtures in the real engine. ReDoS is an application availability bug dressed as a clever pattern. Keep the cleverness small enough to explain.
When a timed fixture fails, I do not widen the budget first. I rewrite nested repetition, add an input cap, or move the check off the request path. Widening the budget without a rewrite teaches the system to accept slow patterns.
Write down the before-and-after fixture times in the ticket so the next reviewer sees the improvement. Keep the adversarial string in CI forever. That single habit prevents quiet regressions when someone later simplifies the pattern without re-running the long cases.
Keep the adversarial fixtures next to the pattern file so reviewers never hunt for them.
Try the product: RegexProof
2026-09-16 · primary sources only · no fabricated traffic metrics
RegexProof converts a natural-language description into a regex for the engine you choose, then explains it part by part and flags edge cases.
You choose the flavor — ECMAScript/JavaScript, PCRE, and others — and should validate against the production dialect, not only a paste-bin tester.
It explains repetition and alternation and calls out patterns prone to catastrophic backtracking, the root cause of ReDoS (Regular-expression Denial of Service).
The Free tier includes 10 forges per month; Pro is $19/mo for higher volume.
Lookbehind support, Unicode modes, and recursive patterns differ across engines, so a pattern valid in PCRE can fail or act differently in JavaScript.