{"title":"Regex Denial of Service via Catastrophic Backtracking","language":"Python","severity":"High","cwe":"CWE-1333","source_lines":[9],"flow_lines":[9,11],"sink_lines":[11],"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]+)+$'\n    if re.match(pattern, sensor_id):\n        return jsonify({'valid': True, 'message': 'Sensor ID format accepted'})\n    return jsonify({'valid': False, 'message': 'Invalid sensor identifier format'}), 400","explanation":"The regex pattern contains nested quantifiers (([a-zA-Z0-9]+)*-)* which causes catastrophic backtracking when processing malicious input. When re.match() attempts to match an input like many alphanumeric characters followed by a dash without proper termination, the regex engine explores exponentially many backtracking paths, leading to CPU exhaustion and denial of service.","remediation":"The fix replaces the vulnerable regex pattern `^(([a-zA-Z0-9]+)*-)*([a-zA-Z0-9]+)+$` with the safe equivalent `^[a-zA-Z0-9]+(-[a-zA-Z0-9]+)*$`, which matches the same logical format (alphanumeric segments separated by dashes) but eliminates nested quantifiers that caused catastrophic backtracking. Additionally, an input length check of 128 characters is added as a defense-in-depth measure to prevent abuse even if future regex changes inadvertently reintroduce complexity.","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) > 128:\n        return jsonify({'valid': False, 'message': 'Invalid sensor identifier format'}), 400\n    \n    # Safe regex without nested quantifiers - matches alphanumeric segments separated by dashes\n    pattern = r'^[a-zA-Z0-9]+(-[a-zA-Z0-9]+)*$'\n    if re.match(pattern, sensor_id):\n        return jsonify({'valid': True, 'message': 'Sensor ID format accepted'})\n    return jsonify({'valid': False, 'message': 'Invalid sensor identifier format'}), 400"}