# Regex Denial of Service via Catastrophic Backtracking

Language: Python
Severity: High
CWE: CWE-1333

## Source
9

## Flow
9-10-4-5

## Sink
5

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

def validate_iot_device_identifier(device_id):
    pattern = r'^(([a-zA-Z0-9]+)*-)*([a-zA-Z0-9]+)+$'
    if re.match(pattern, device_id):
        return jsonify({'status': 'valid', 'device': device_id})
    return jsonify({'status': 'invalid'})

@app.route('/api/iot/register', methods=['POST'])
def register_sensor():
    sensor_id = request.json.get('sensor_identifier', '')
    return validate_iot_device_identifier(sensor_id)
```

## Explanation

The regex pattern contains nested quantifiers (([a-zA-Z0-9]+)*-)* which causes catastrophic backtracking when matching fails. When an attacker submits a long string of alphanumeric characters followed by a hyphen, the regex engine explores exponentially many matching possibilities, leading to CPU exhaustion and denial of service.

## Remediation

The fix replaces the vulnerable regex pattern `^(([a-zA-Z0-9]+)*-)*([a-zA-Z0-9]+)+$` which had nested quantifiers causing catastrophic backtracking, with a safe equivalent `^[a-zA-Z0-9]+(-[a-zA-Z0-9]+)*$` that matches the same valid inputs (hyphen-separated alphanumeric segments) without any nested quantifiers. Additionally, an input length check is added as a defense-in-depth measure to cap processing time even if future regex changes introduce issues.

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

def validate_iot_device_identifier(device_id):
    # Limit input length to prevent abuse
    if not device_id or len(device_id) > 256:
        return jsonify({'status': 'invalid'})
    # Use a non-backtracking regex pattern that matches hyphenated alphanumeric identifiers
    pattern = r'^[a-zA-Z0-9]+(-[a-zA-Z0-9]+)*$'
    if re.match(pattern, device_id):
        return jsonify({'status': 'valid', 'device': device_id})
    return jsonify({'status': 'invalid'})

@app.route('/api/iot/register', methods=['POST'])
def register_sensor():
    sensor_id = request.json.get('sensor_identifier', '')
    return validate_iot_device_identifier(sensor_id)
```
