{"title":"XML Entity Expansion via Exponential Entity Expansion (Billion Laughs)","language":"Python","severity":"High","cwe":"CWE-776","source_lines":[8],"flow_lines":[8,10],"sink_lines":[10],"vulnerable_code":"import xml.etree.ElementTree as ET\nfrom flask import Flask, request, jsonify\n\napp = Flask(__name__)\n\n@app.route('/iot/device/config', methods=['POST'])\ndef process_device_config():\n    device_xml = request.data.decode('utf-8')\n    try:\n        config_tree = ET.fromstring(device_xml)\n        device_id = config_tree.find('device_id').text\n        settings = {child.tag: child.text for child in config_tree.find('settings')}\n        return jsonify({'status': 'configured', 'device': device_id, 'applied_settings': settings})\n    except Exception as e:\n        return jsonify({'error': 'Configuration parsing failed', 'details': str(e)}), 400","explanation":"The application accepts untrusted XML data from the HTTP request body and parses it directly using ET.fromstring() without any protection against XML entity expansion attacks. The standard xml.etree.ElementTree parser is vulnerable to Billion Laughs (exponential entity expansion) attacks where malicious XML with nested entity definitions can cause exponential memory consumption and DoS.","remediation":"The fix replaces the standard `xml.etree.ElementTree` module with `defusedxml.ElementTree`, which provides protection against XML entity expansion attacks (Billion Laughs), external entity attacks (XXE), and other XML-based exploits. The defusedxml library raises an exception when it detects malicious entity definitions, preventing resource exhaustion.","secure_code":"import defusedxml.ElementTree as ET\nfrom flask import Flask, request, jsonify\n\napp = Flask(__name__)\n\n@app.route('/iot/device/config', methods=['POST'])\ndef process_device_config():\n    device_xml = request.data.decode('utf-8')\n    try:\n        config_tree = ET.fromstring(device_xml)\n        device_id = config_tree.find('device_id').text\n        settings = {child.tag: child.text for child in config_tree.find('settings')}\n        return jsonify({'status': 'configured', 'device': device_id, 'applied_settings': settings})\n    except Exception as e:\n        return jsonify({'error': 'Configuration parsing failed', 'details': str(e)}), 400"}