{"title":"Regex DoS via Catastrophic Backtracking in re.search()","language":"Python","severity":"High","cwe":"CWE-1333","source_lines":[8],"flow_lines":[8,10],"sink_lines":[10],"vulnerable_code":"import re\nfrom flask import Flask, request, jsonify\n\napp = Flask(__name__)\n\n@app.route('/api/iot/device/validate', methods=['POST'])\ndef validate_device_identifier():\n    device_id = request.json.get('device_identifier', '')\n    pattern = r'^(([a-zA-Z0-9]+)+)+@iot\\.local$'\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 contains nested quantifiers (([a-zA-Z0-9]+)+)+ that cause catastrophic backtracking when processing malicious input. When re.search() attempts to match a string with many repeating characters followed by a non-matching character, the regex engine explores an exponential number of backtracking paths, leading to ReDoS (Regular Expression Denial of Service).","remediation":"The fix replaces the vulnerable nested quantifier pattern (([a-zA-Z0-9]+)+)+ with a simple non-nested quantifier [a-zA-Z0-9]+ which matches the same valid inputs (one or more alphanumeric characters before @iot.local) without any backtracking risk. Additionally, an input length check is added as a defense-in-depth measure to prevent processing excessively long strings.","secure_code":"import re\nfrom flask import Flask, request, jsonify\n\napp = Flask(__name__)\n\n@app.route('/api/iot/device/validate', methods=['POST'])\ndef validate_device_identifier():\n    device_id = request.json.get('device_identifier', '')\n    if len(device_id) > 255:\n        return jsonify({'status': 'invalid'}), 400\n    pattern = r'^[a-zA-Z0-9]+@iot\\.local$'\n    if re.search(pattern, device_id):\n        return jsonify({'status': 'valid', 'device': device_id})\n    return jsonify({'status': 'invalid'}), 400"}