# Regular Expression Denial of Service via Catastrophic Backtracking

Language: Python
Severity: High
CWE: CWE-1333

## Source
9

## Flow
9-10-11

## Sink
11

## Vulnerable Code
```python
import re
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/api/iot/device/validate', methods=['POST'])
def validate_device_signature():
    device_sig = request.json.get('device_signature', '')
    sig_pattern = r'^(([a-zA-Z0-9]+)*:)+([a-zA-Z0-9]+)*$'
    if re.match(sig_pattern, device_sig):
        return jsonify({'status': 'valid', 'device_authorized': True})
    return jsonify({'status': 'invalid', 'device_authorized': False}), 403
```

## Explanation

The regex pattern `^(([a-zA-Z0-9]+)*:)+([a-zA-Z0-9]+)*$` contains nested quantifiers that cause catastrophic backtracking. When untrusted input from `device_signature` contains repeated characters followed by colons, the regex engine explores exponential paths, leading to CPU exhaustion and DoS.

## Remediation

The fix removes the nested quantifiers `([a-zA-Z0-9]+)*` that caused catastrophic backtracking by simplifying the pattern to `([a-zA-Z0-9]+:)+[a-zA-Z0-9]+$`, which matches one or more colon-separated alphanumeric segments without ambiguity. Additionally, an input length limit of 256 characters is enforced to provide defense-in-depth against potential abuse.

## Secure Code
```python
import re
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/api/iot/device/validate', methods=['POST'])
def validate_device_signature():
    device_sig = request.json.get('device_signature', '')
    
    # Input length limit to prevent abuse
    if not device_sig or len(device_sig) > 256:
        return jsonify({'status': 'invalid', 'device_authorized': False}), 403
    
    # Safe regex without nested quantifiers
    sig_pattern = r'^([a-zA-Z0-9]+:)+[a-zA-Z0-9]+$'
    if re.match(sig_pattern, device_sig):
        return jsonify({'status': 'valid', 'device_authorized': True})
    return jsonify({'status': 'invalid', 'device_authorized': False}), 403
```
