{"title":"Regex Denial of Service via Catastrophic Backtracking","language":"Python","severity":"High","cwe":"CWE-1333","source_lines":[8],"flow_lines":[8,9],"sink_lines":[9],"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]+)*-)*([a-zA-Z0-9]+)+$'\n    if re.match(pattern, device_id):\n        return jsonify({'status': 'valid', 'device_id': device_id})\n    return jsonify({'status': 'invalid'}), 400","explanation":"The regex pattern contains nested quantifiers (([a-zA-Z0-9]+)*-)* and ([a-zA-Z0-9]+)+ which cause catastrophic backtracking. When a malicious device_id with repeating characters followed by an invalid ending is submitted, the regex engine explores exponentially many backtracking paths, causing CPU exhaustion and denial of service.","remediation":"The fix replaces the vulnerable regex pattern that had nested quantifiers (([a-zA-Z0-9]+)*-)* and ([a-zA-Z0-9]+)+ with a safe linear-time pattern ^[a-zA-Z0-9]+(-[a-zA-Z0-9]+)*$ that matches the same valid device ID format (alphanumeric segments separated by hyphens) without any nested quantifiers. An input length check is also added as defense-in-depth to limit the maximum size of device identifiers processed.","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    \n    # Limit input length to prevent abuse\n    if not device_id or len(device_id) > 256:\n        return jsonify({'status': 'invalid'}), 400\n    \n    # Safe regex without nested quantifiers - matches segments of alphanumeric chars separated by hyphens\n    pattern = r'^[a-zA-Z0-9]+(-[a-zA-Z0-9]+)*$'\n    if re.match(pattern, device_id):\n        return jsonify({'status': 'valid', 'device_id': device_id})\n    return jsonify({'status': 'invalid'}), 400"}