{"title":"XML External Entity (XXE) Injection via lxml.etree.parse on Untrusted XML","language":"Python","severity":"Critical","cwe":"CWE-611","source_lines":[5],"flow_lines":[5,7],"sink_lines":[7],"vulnerable_code":"from lxml import etree\nimport boto3\n\ndef process_iot_device_telemetry(device_xml_payload, s3_bucket):\n    s3_client = boto3.client('s3')\n    parser = etree.XMLParser(resolve_entities=True, no_network=False)\n    telemetry_doc = etree.fromstring(device_xml_payload.encode(), parser)\n    device_id = telemetry_doc.find('.//DeviceID').text\n    sensor_data = telemetry_doc.find('.//SensorReadings').text\n    metadata_key = f\"telemetry/{device_id}/latest.xml\"\n    s3_client.put_object(Bucket=s3_bucket, Key=metadata_key, Body=device_xml_payload)\n    return {\"device\": device_id, \"data\": sensor_data, \"stored\": metadata_key}","explanation":"The function accepts untrusted XML input from IoT devices and parses it with lxml.etree using a parser explicitly configured with resolve_entities=True and no_network=False. This allows XXE attacks where malicious XML can reference external entities to read local files, perform SSRF attacks, or cause denial of service.","remediation":"The fix secures the XML parser by setting resolve_entities=False to prevent external entity expansion, no_network=True to block network access during parsing, and explicitly disabling DTD loading and validation. These settings prevent XXE attacks where malicious XML payloads could reference external entities to exfiltrate data or perform SSRF.","secure_code":"from lxml import etree\nimport boto3\n\ndef process_iot_device_telemetry(device_xml_payload, s3_bucket):\n    s3_client = boto3.client('s3')\n    parser = etree.XMLParser(resolve_entities=False, no_network=True, dtd_validation=False, load_dtd=False)\n    telemetry_doc = etree.fromstring(device_xml_payload.encode(), parser)\n    device_id = telemetry_doc.find('.//DeviceID').text\n    sensor_data = telemetry_doc.find('.//SensorReadings').text\n    metadata_key = f\"telemetry/{device_id}/latest.xml\"\n    s3_client.put_object(Bucket=s3_bucket, Key=metadata_key, Body=device_xml_payload)\n    return {\"device\": device_id, \"data\": sensor_data, \"stored\": metadata_key}"}