{"title":"Regular Expression Denial of Service via Catastrophic Backtracking","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_sensor_id', methods=['POST'])\ndef validate_iot_sensor_identifier():\n    sensor_id = request.json.get('sensor_id', '')\n    pattern = r'^(([a-zA-Z0-9]+)+)+@(([a-zA-Z0-9]+)+)+\\.(([a-zA-Z]+)+)+$'\n    compiled_regex = re.compile(pattern)\n    if compiled_regex.match(sensor_id):\n        return jsonify({\n            'valid': True,\n            'message': 'Sensor ID format accepted',\n            'device_id': sensor_id\n        })\n    else:\n        return jsonify({\n            'valid': False,\n            'message': 'Invalid sensor identifier format'\n        }), 400","explanation":"The regex pattern contains nested quantifiers `(([a-zA-Z0-9]+)+)+` that cause catastrophic backtracking when matching fails. An attacker can submit a sensor_id with many repeating characters followed by an invalid character, forcing the regex engine to explore exponentially many backtracking paths, leading to CPU exhaustion and DoS.","remediation":"The fix removes the nested quantifiers `(([a-zA-Z0-9]+)+)+` that caused catastrophic backtracking and replaces them with simple, non-nested character class matches `[a-zA-Z0-9]+`. Additionally, an input length check is added as a defense-in-depth measure to prevent excessively long inputs from being processed.","secure_code":"import re\nfrom flask import Flask, request, jsonify\n\napp = Flask(__name__)\n\n@app.route('/api/iot/validate_sensor_id', methods=['POST'])\ndef validate_iot_sensor_identifier():\n    sensor_id = request.json.get('sensor_id', '')\n    \n    # Input length limit to prevent abuse\n    if not sensor_id or len(sensor_id) > 254:\n        return jsonify({\n            'valid': False,\n            'message': 'Invalid sensor identifier format'\n        }), 400\n    \n    # Safe regex without nested quantifiers\n    pattern = r'^[a-zA-Z0-9]+@[a-zA-Z0-9]+\\.[a-zA-Z]+$'\n    compiled_regex = re.compile(pattern)\n    if compiled_regex.match(sensor_id):\n        return jsonify({\n            'valid': True,\n            'message': 'Sensor ID format accepted',\n            'device_id': sensor_id\n        })\n    else:\n        return jsonify({\n            'valid': False,\n            'message': 'Invalid sensor identifier format'\n        }), 400"}