{"title":"Regular Expression 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_signature():\n    device_sig = request.json.get('device_signature', '')\n    sig_pattern = r'^(([a-zA-Z0-9]+)*:)+([a-zA-Z0-9]+)*$'\n    if re.match(sig_pattern, device_sig):\n        return jsonify({'status': 'valid', 'device_authorized': True})\n    return jsonify({'status': 'invalid', 'device_authorized': False}), 403","explanation":"The regex pattern `^(([a-zA-Z0-9]+)*:)+([a-zA-Z0-9]+)*$` contains nested quantifiers that cause catastrophic backtracking. When untrusted input from `device_signature` contains repeated characters followed by colons, the regex engine explores exponential paths, leading to CPU exhaustion and DoS.","remediation":"The fix removes the nested quantifiers `([a-zA-Z0-9]+)*` that caused catastrophic backtracking by simplifying the pattern to `([a-zA-Z0-9]+:)+[a-zA-Z0-9]+$`, which matches one or more colon-separated alphanumeric segments without ambiguity. Additionally, an input length limit of 256 characters is enforced to provide defense-in-depth against potential abuse.","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_signature():\n    device_sig = request.json.get('device_signature', '')\n    \n    # Input length limit to prevent abuse\n    if not device_sig or len(device_sig) > 256:\n        return jsonify({'status': 'invalid', 'device_authorized': False}), 403\n    \n    # Safe regex without nested quantifiers\n    sig_pattern = r'^([a-zA-Z0-9]+:)+[a-zA-Z0-9]+$'\n    if re.match(sig_pattern, device_sig):\n        return jsonify({'status': 'valid', 'device_authorized': True})\n    return jsonify({'status': 'invalid', 'device_authorized': False}), 403"}