{"title":"XML External Entity (XXE) Injection","language":"Python","severity":"Critical","cwe":"CWE-611","source_lines":[6],"flow_lines":[6,9,10,11,12],"sink_lines":[10],"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_payload = request.data\n    if not raw_payload:\n        return jsonify({'err': 'empty payload'}), 400\n    parser = etree.XMLParser(resolve_entities=True, no_network=False)\n    dev_tree = etree.fromstring(raw_payload, parser)\n    sensor_id = dev_tree.findtext('.//sensorId')\n    readings = dev_tree.findtext('.//readings')\n    return jsonify({'sensor': sensor_id, 'data': readings}), 200","explanation":"The application reads raw XML data directly from the HTTP request body (line 6) and parses it using an lxml XMLParser configured with resolve_entities=True and no_network=False (line 9). This allows an attacker to embed external entity declarations (XXE) in the XML payload, enabling arbitrary file reads from the server filesystem or SSRF against internal network endpoints. The tainted input flows directly into etree.fromstring() without any sanitization or safe parser configuration.","remediation":"The fix configures the lxml XMLParser with resolve_entities=False, no_network=True, dtd_validation=False, and load_dtd=False, which collectively prevent the parser from resolving external (and internal) entity references and from loading any external DTDs or making network requests. Additionally, XML parsing is wrapped in a try/except block to gracefully handle malformed or malicious XML payloads that might cause parsing errors.","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_payload = request.data\n    if not raw_payload:\n        return jsonify({'err': 'empty payload'}), 400\n    parser = etree.XMLParser(resolve_entities=False, no_network=True, dtd_validation=False, load_dtd=False)\n    try:\n        dev_tree = etree.fromstring(raw_payload, parser)\n    except etree.XMLSyntaxError:\n        return jsonify({'err': 'invalid XML payload'}), 400\n    sensor_id = dev_tree.findtext('.//sensorId')\n    readings = dev_tree.findtext('.//readings')\n    return jsonify({'sensor': sensor_id, 'data': readings}), 200"}