# Regular Expression Denial of Service via Catastrophic Backtracking

Language: Python
Severity: High
CWE: CWE-1333

## Source
8

## Flow
8-9-10

## Sink
10

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

app = Flask(__name__)

@app.route('/api/iot/validate_sensor_id', methods=['POST'])
def validate_iot_sensor_identifier():
    sensor_id = request.json.get('sensor_id', '')
    pattern = r'^(([a-zA-Z0-9]+)+)+@(([a-zA-Z0-9]+)+)+\.(([a-zA-Z]+)+)+$'
    compiled_regex = re.compile(pattern)
    if compiled_regex.match(sensor_id):
        return jsonify({
            'valid': True,
            'message': 'Sensor ID format accepted',
            'device_id': sensor_id
        })
    else:
        return jsonify({
            'valid': False,
            'message': 'Invalid sensor identifier format'
        }), 400
```

## Explanation

The regex pattern contains nested quantifiers `(([a-zA-Z0-9]+)+)+` that cause catastrophic backtracking when matching fails. An attacker can submit a sensor_id with many repeating characters followed by an invalid character, forcing the regex engine to explore exponentially many backtracking paths, leading to CPU exhaustion and DoS.

## Remediation

The fix removes the nested quantifiers `(([a-zA-Z0-9]+)+)+` that caused catastrophic backtracking and replaces them with simple, non-nested character class matches `[a-zA-Z0-9]+`. Additionally, an input length check is 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_id', methods=['POST'])
def validate_iot_sensor_identifier():
    sensor_id = request.json.get('sensor_id', '')
    
    # Input length limit to prevent abuse
    if not sensor_id or len(sensor_id) > 254:
        return jsonify({
            'valid': False,
            'message': 'Invalid sensor identifier format'
        }), 400
    
    # Safe regex without nested quantifiers
    pattern = r'^[a-zA-Z0-9]+@[a-zA-Z0-9]+\.[a-zA-Z]+$'
    compiled_regex = re.compile(pattern)
    if compiled_regex.match(sensor_id):
        return jsonify({
            'valid': True,
            'message': 'Sensor ID format accepted',
            'device_id': sensor_id
        })
    else:
        return jsonify({
            'valid': False,
            'message': 'Invalid sensor identifier format'
        }), 400
```
