# Regex Denial of Service via Catastrophic Backtracking

Language: Python
Severity: High
CWE: CWE-1333

## Source
8

## Flow
8-9

## Sink
9

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

app = Flask(__name__)

@app.route('/api/iot/validate_device_id', methods=['POST'])
def validate_iot_device_identifier():
    device_id = request.json.get('device_identifier', '')
    pattern = r'^(([a-zA-Z0-9]+)*-)*([a-zA-Z0-9]+)+$'
    if re.match(pattern, device_id):
        return jsonify({'status': 'valid', 'device_id': device_id})
    return jsonify({'status': 'invalid'}), 400
```

## Explanation

The regex pattern contains nested quantifiers (([a-zA-Z0-9]+)*-)* and ([a-zA-Z0-9]+)+ which cause catastrophic backtracking. When a malicious device_id with repeating characters followed by an invalid ending is submitted, the regex engine explores exponentially many backtracking paths, causing CPU exhaustion and denial of service.

## Remediation

The fix replaces the vulnerable regex pattern that had nested quantifiers (([a-zA-Z0-9]+)*-)* and ([a-zA-Z0-9]+)+ with a safe linear-time pattern ^[a-zA-Z0-9]+(-[a-zA-Z0-9]+)*$ that matches the same valid device ID format (alphanumeric segments separated by hyphens) without any nested quantifiers. An input length check is also added as defense-in-depth to limit the maximum size of device identifiers processed.

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

app = Flask(__name__)

@app.route('/api/iot/validate_device_id', methods=['POST'])
def validate_iot_device_identifier():
    device_id = request.json.get('device_identifier', '')
    
    # Limit input length to prevent abuse
    if not device_id or len(device_id) > 256:
        return jsonify({'status': 'invalid'}), 400
    
    # Safe regex without nested quantifiers - matches segments of alphanumeric chars separated by hyphens
    pattern = r'^[a-zA-Z0-9]+(-[a-zA-Z0-9]+)*$'
    if re.match(pattern, device_id):
        return jsonify({'status': 'valid', 'device_id': device_id})
    return jsonify({'status': 'invalid'}), 400
```
