{"title":"Regex Denial of Service via Catastrophic Backtracking","language":"Python","severity":"High","cwe":"CWE-1333","source_lines":[9],"flow_lines":[9,10,11],"sink_lines":[11],"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]+)+)+\\-[0-9]{4}$'\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 `^(([a-zA-Z0-9]+)+)+\\-[0-9]{4}$` contains nested quantifiers that cause catastrophic backtracking. When untrusted input from the JSON request body contains many alphanumeric characters followed by a non-matching character, the regex engine exponentially backtracks, leading to CPU exhaustion and denial of service.","remediation":"The fix replaces the vulnerable regex pattern `^(([a-zA-Z0-9]+)+)+\\-[0-9]{4}$` with the safe equivalent `^[a-zA-Z0-9]+\\-[0-9]{4}$`, which eliminates the nested quantifiers that caused exponential backtracking. Additionally, an input length check (max 128 characters) is added as a defense-in-depth measure to limit resource consumption even if future regex changes introduce issues.","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    \n    # Input length limit to prevent abuse\n    if not device_id or len(device_id) > 128:\n        return jsonify({'status': 'invalid'}), 400\n    \n    # Fixed regex: removed nested quantifiers to prevent catastrophic backtracking\n    # Pattern matches one or more alphanumeric characters followed by a hyphen and exactly 4 digits\n    pattern = r'^[a-zA-Z0-9]+\\-[0-9]{4}$'\n    if re.match(pattern, device_id):\n        return jsonify({'status': 'valid', 'device_id': device_id})\n    return jsonify({'status': 'invalid'}), 400"}