Vulnerable Patterns¶
This guide shows common vulnerable regex patterns, explains why they're dangerous, and provides safe alternatives.
Pattern Categories¶
1. Nested Quantifiers¶
The most common source of exponential complexity.
Vulnerable
Why it's dangerous: The inner quantifier creates ambiguity about how to distribute characters among repetitions.
from redoctor import check
result = check(r"^(a+)+$")
print(result.complexity) # O(2^n)
print(result.attack) # 'aaaaaaaaaaaaaaaaaaa!'
2. Overlapping Alternatives¶
Alternatives that can match the same input.
Vulnerable
Why it's dangerous: Multiple paths can match the same input, causing backtracking.
3. Greedy Wildcards¶
Multiple .+ or .* patterns.
Safe Alternative
Why it's dangerous: Each .* can consume varying amounts, creating combinatorial explosion.
4. Email Patterns¶
Email validation is a common source of ReDoS.
Safe Alternative
5. URL Patterns¶
URL parsing with regex is tricky.
Safe Alternative
6. HTML/XML Patterns¶
Don't parse HTML with regex!
Safe Alternative
7. Whitespace Handling¶
Trimming and normalizing whitespace.
Complexity Reference¶
| Pattern | Complexity | Risk |
|---|---|---|
^(a+)+$ | O(2^n) | šØ Critical |
(a\|a)+ | O(2^n) | šØ Critical |
.*a.*a.* | O(n²) | ā ļø High |
(a+)+b | O(2^n) | šØ Critical |
^[a-z]+$ | O(n) | ā Safe |
^\d{1,10}$ | O(n) | ā Safe |
Test with ReDoctor¶
from redoctor import check
patterns = [
r"^(a+)+$",
r"(a|a)*$",
r".*a.*a.*",
r"^[a-z]+$",
]
for pattern in patterns:
result = check(pattern)
status = "šØ VULN" if result.is_vulnerable else "ā
SAFE"
complexity = result.complexity.summary if result.complexity else "N/A"
print(f"{status} {complexity:8} {pattern}")
Output:
Quick Reference Card¶
Avoid These Patterns¶
| Pattern | Problem |
|---|---|
(x+)+ | Nested quantifiers |
(x\|x)+ | Overlapping alternatives |
.*x.*x.* | Multiple wildcards |
(x*)* | Star within star |
(x+x+)+ | Overlapping within group |
Safe Alternatives¶
| Instead of | Use |
|---|---|
(a+)+ | a+ |
(a\|ab)+ | (ab?)+ |
.*a.* | [^a]*a.* |
(\w+\s+)+ | (\w+\s)+ or validate differently |