# Regex 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_identifier():
    device_id = request.json.get('device_identifier', '')
    pattern = r'^(([a-zA-Z0-9]+)+)+\-[0-9]{4}$'
    if re.match(pattern, device_id):
        return jsonify({'status': 'valid', 'device_id': device_id})
    return jsonify({'status': 'invalid'}), 400
```

## Explanation

The regex pattern `^(([a-zA-Z0-9]+)+)+\-[0-9]{4}$` contains nested quantifiers that cause catastrophic backtracking. When untrusted input from the JSON request body contains many alphanumeric characters followed by a non-matching character, the regex engine exponentially backtracks, leading to CPU exhaustion and denial of service.

## Remediation

The fix replaces the vulnerable regex pattern `^(([a-zA-Z0-9]+)+)+\-[0-9]{4}$` with the safe equivalent `^[a-zA-Z0-9]+\-[0-9]{4}$`, which eliminates the nested quantifiers that caused exponential backtracking. Additionally, an input length check (max 128 characters) is added as a defense-in-depth measure to limit resource consumption even if future regex changes introduce issues.

## 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_identifier():
    device_id = request.json.get('device_identifier', '')
    
    # Input length limit to prevent abuse
    if not device_id or len(device_id) > 128:
        return jsonify({'status': 'invalid'}), 400
    
    # Fixed regex: removed nested quantifiers to prevent catastrophic backtracking
    # Pattern matches one or more alphanumeric characters followed by a hyphen and exactly 4 digits
    pattern = r'^[a-zA-Z0-9]+\-[0-9]{4}$'
    if re.match(pattern, device_id):
        return jsonify({'status': 'valid', 'device_id': device_id})
    return jsonify({'status': 'invalid'}), 400
```
