{"title":"Regex Denial of Service via Catastrophic Backtracking in `re.search`","language":"Python","severity":"High","cwe":"CWE-1333","source_lines":[8],"flow_lines":[8,9,10],"sink_lines":[10],"vulnerable_code":"import re\nfrom flask import Flask, request, jsonify\n\napp = Flask(__name__)\n\n@app.route('/api/iot/validate_device_id', methods=['POST'])\ndef validate_iot_device_identifier():\n    device_id = request.json.get('device_identifier', '')\n    pattern = r'^(([a-zA-Z0-9]+)+)+@iot\\.device$'\n    if re.search(pattern, device_id):\n        return jsonify({'status': 'valid', 'device': device_id})\n    return jsonify({'status': 'invalid'}), 400","explanation":"The regex pattern `r'^(([a-zA-Z0-9]+)+)+@iot\\.device$'` contains nested quantifiers that cause catastrophic backtracking. When an attacker sends a malformed device_id with many repeating characters followed by a non-matching suffix, the regex engine explores exponentially many backtracking paths, causing CPU exhaustion and denial of service.","remediation":"The fix replaces the vulnerable regex pattern `r'^(([a-zA-Z0-9]+)+)+@iot\\.device$'` with `r'^[a-zA-Z0-9]+@iot\\.device$'`, which removes the nested quantifiers that caused catastrophic backtracking. The simplified pattern still correctly validates that the device ID consists of one or more alphanumeric characters followed by the literal `@iot.device` suffix, but executes in linear time.","secure_code":"import re\nfrom flask import Flask, request, jsonify\n\napp = Flask(__name__)\n\n@app.route('/api/iot/validate_device_id', methods=['POST'])\ndef validate_iot_device_identifier():\n    device_id = request.json.get('device_identifier', '')\n    pattern = r'^[a-zA-Z0-9]+@iot\\.device$'\n    if re.search(pattern, device_id):\n        return jsonify({'status': 'valid', 'device': device_id})\n    return jsonify({'status': 'invalid'}), 400"}