{"title":"XML External Entity (XXE) Injection","language":"Python","severity":"Critical","cwe":"CWE-611","source_lines":[6],"flow_lines":[6,7,8],"sink_lines":[8],"vulnerable_code":"from lxml import etree\nfrom flask import Flask, request, jsonify\napp = Flask(__name__)\n@app.route('/iot/device/config', methods=['POST'])\ndef parse_device_telemetry():\n    raw_xml = request.data\n    parser = etree.XMLParser(resolve_entities=True, no_network=False)\n    try:\n        dev_tree = etree.fromstring(raw_xml, parser)\n        sensor_id = dev_tree.findtext('.//sensorId')\n        payload_val = dev_tree.findtext('.//reading')\n        return jsonify({'sensor': sensor_id, 'value': payload_val})\n    except etree.XMLSyntaxError as xe:\n        return jsonify({'err': str(xe)}), 400","explanation":"The endpoint reads raw XML from the HTTP request body (line 6) without any sanitization, then constructs an lxml XMLParser with resolve_entities=True and no_network=False (line 7), which explicitly enables external entity resolution and network access. When this misconfigured parser processes the untrusted XML via etree.fromstring() (line 8), an attacker can inject an XXE payload containing an external entity referencing local files (e.g., file:///etc/passwd) or internal network resources (SSRF), causing the server to disclose sensitive data.","remediation":"The fix secures the lxml XMLParser by setting resolve_entities=False and no_network=True, which prevents the parser from resolving external (and internal) entity references and blocks any network access during parsing. Additionally, dtd_validation=False and load_dtd=False are set to prevent DTD loading entirely, providing defense-in-depth against all XXE attack vectors including file disclosure and SSRF.","secure_code":"from lxml import etree\nfrom flask import Flask, request, jsonify\napp = Flask(__name__)\n@app.route('/iot/device/config', methods=['POST'])\ndef parse_device_telemetry():\n    raw_xml = request.data\n    parser = etree.XMLParser(resolve_entities=False, no_network=True, dtd_validation=False, load_dtd=False)\n    try:\n        dev_tree = etree.fromstring(raw_xml, parser)\n        sensor_id = dev_tree.findtext('.//sensorId')\n        payload_val = dev_tree.findtext('.//reading')\n        return jsonify({'sensor': sensor_id, 'value': payload_val})\n    except etree.XMLSyntaxError as xe:\n        return jsonify({'err': str(xe)}), 400"}