{"title":"Billion Laughs Denial of Service via XML Entity Expansion","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\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, 'settings': settings})\n    except Exception as e:\n        return jsonify({'error': str(e)}), 400","explanation":"The application parses untrusted XML data from IoT devices using ET.fromstring() without disabling external entity processing or entity expansion. This allows attackers to send specially crafted XML with recursive entity definitions that exponentially expand in memory, causing a Billion Laughs (XML bomb) denial of service attack.","remediation":"The fix replaces the standard `xml.etree.ElementTree` module with `defusedxml.ElementTree`, which is a drop-in replacement that automatically prevents XML entity expansion attacks (Billion Laughs), external entity processing (XXE), and other XML-based attacks. The defusedxml library raises an exception when it encounters potentially malicious DTD definitions or entity expansions, stopping the attack before memory exhaustion occurs.","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\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, 'settings': settings})\n    except Exception as e:\n        return jsonify({'error': str(e)}), 400"}