T09 · Insecure Skill Coding Practices
- Location
scripts/regex.py:21- Finding
Unbounded Regular Expression Evaluation Enables Denial of Service
- Content
View full analysis
Vulnerability Details
File Location:
scripts/regex.py, lines 21-42
Vulnerability Type: Regular Expression Denial of Service (ReDoS)
Risk Level: MediumVulnerable Code
python regex = re.compile(pattern, flags) if replace: # Replacement mode if find_all: result = regex.sub(replace, text) else: result = regex.sub(replace, text, count=1) print(result) elif find_all: # Find all matches matches = regex.findall(text) if verbose: for i, match in enumerate(matches): print(f"{i+1}: {match}") else: for match in matches: print(match) else: # Single match match = regex.search(text)Technical Analysis
The script compiles a user-controlled regular expression and evaluates it against user-controlled text using Python's backtracking
reengine. Thesearch,findall, andsuboperations have no execution timeout, input-size limit, pattern-complexity restriction, or isolation mechanism.Patterns containing nested or ambiguous quantifiers can cause catastrophic backtracking. Processing time may grow exponentially with input length when such a pattern nearly matches a long input but fails near its end.
Attack Path
- An attacker invokes the tool with a pathological expression, such as
^(a+)+$. - The attacker supplies a sufficiently long near-matching string consisting of repeated
acharacters followed by a non-matching character, either as the positional text argument or through standard input. - For example, the vulnerable matching path can be reached with:
bash python3 scripts/regex.py '^(a+)+$' 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!' regex.search(text)repeatedly explores overlapping backtracking states while attempting to prove that the input does not match.- Increasing the input length can cause the process to consume excessive CPU an ...[truncated 666 chars]
- An attacker invokes the tool with a pathological expression, such as
- Remediation
View remediation
Remediation Suggestions
- Use a regular-expression implementation that supports a native per-operation timeout, and enforce a short maximum execution duration for every search, substitution, and global match.
- If native timeouts are unavailable, execute regex processing in an isolated subprocess with strict wall-clock, CPU, and memory limits. Terminate the subprocess when any limit is exceeded.
- Define conservative maximum lengths for both patterns and input text before compilation or evaluation.
- Reject or separately review high-risk constructions such as nested quantifiers, ambiguous alternations, and quantified groups containing overlapping matches. Treat this only as defense in depth because static detection cannot identify every pathological expression.
- Return a controlled error when a timeout or resource limit is reached.
- Add regression tests using known catastrophic-backtracking patterns and long near-matching inputs to verify that processing terminates within the configured limit.
