# Regex Denial of Service via Catastrophic Backtracking

Language: Python
Severity: High
CWE: CWE-1333

## Source
9

## Flow
9-11

## Sink
11

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

app = Flask(__name__)

@app.route('/api/iot/validate_sensor_data', methods=['POST'])
def validate_sensor_telemetry():
    telemetry_payload = request.json.get('sensor_output', '')
    pattern = r'^(([a-zA-Z0-9]+)+)+@device\.(local|cloud)$'
    if re.match(pattern, telemetry_payload):
        return jsonify({'status': 'valid', 'processed': True})
    return jsonify({'status': 'invalid', 'processed': False}), 400
```

## Explanation

The regex pattern contains nested quantifiers (([a-zA-Z0-9]+)+)+ which causes catastrophic backtracking. When untrusted input from request.json is passed to re.match(), a specially crafted input with repetitive characters followed by a non-matching suffix forces exponential time complexity, enabling ReDoS attacks that can hang the server.

## Remediation

The fix removes the nested quantifiers (([a-zA-Z0-9]+)+)+ which caused catastrophic backtracking, replacing them with a single [a-zA-Z0-9]+ character class that matches one or more alphanumeric characters without any nesting. An input length check is also added as a defense-in-depth measure to prevent excessively long inputs from being processed.

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

app = Flask(__name__)

@app.route('/api/iot/validate_sensor_data', methods=['POST'])
def validate_sensor_telemetry():
    telemetry_payload = request.json.get('sensor_output', '')
    if len(telemetry_payload) > 256:
        return jsonify({'status': 'invalid', 'processed': False}), 400
    pattern = r'^[a-zA-Z0-9]+@device\.(local|cloud)$'
    if re.match(pattern, telemetry_payload):
        return jsonify({'status': 'valid', 'processed': True})
    return jsonify({'status': 'invalid', 'processed': False}), 400
```
