{"title":"XXE via lxml.etree.fromstring with resolve_entities=True","language":"Python","severity":"Critical","cwe":"CWE-611","source_lines":[1],"flow_lines":[1,6,7],"sink_lines":[7],"vulnerable_code":"from lxml import etree\nimport boto3\n\ndef process_iot_device_config(device_xml_payload):\n    s3_client = boto3.client('s3')\n    parser = etree.XMLParser(resolve_entities=True, no_network=False)\n    device_config = etree.fromstring(device_xml_payload.encode(), parser)\n    device_id = device_config.find('.//deviceId').text\n    firmware_version = device_config.find('.//firmware').text\n    config_data = etree.tostring(device_config, encoding='unicode')\n    s3_client.put_object(Bucket='iot-device-configs', Key=f'{device_id}.xml', Body=config_data)\n    return {'status': 'configured', 'device': device_id, 'version': firmware_version}","explanation":"The code creates an XML parser with resolve_entities=True and no_network=False, then parses untrusted XML input from IoT devices using etree.fromstring(). This allows XML External Entity (XXE) attacks where malicious XML can read local files, perform SSRF attacks, or cause denial of service through entity expansion bombs.","remediation":"The fix disables XML external entity processing by setting resolve_entities=False and no_network=True, and additionally disables DTD loading and validation with dtd_validation=False and load_dtd=False. This prevents attackers from injecting malicious entity declarations that could read local files, perform SSRF attacks, or cause denial of service.","secure_code":"from lxml import etree\nimport boto3\n\ndef process_iot_device_config(device_xml_payload):\n    s3_client = boto3.client('s3')\n    parser = etree.XMLParser(resolve_entities=False, no_network=True, dtd_validation=False, load_dtd=False)\n    device_config = etree.fromstring(device_xml_payload.encode(), parser)\n    device_id = device_config.find('.//deviceId').text\n    firmware_version = device_config.find('.//firmware').text\n    config_data = etree.tostring(device_config, encoding='unicode')\n    s3_client.put_object(Bucket='iot-device-configs', Key=f'{device_id}.xml', Body=config_data)\n    return {'status': 'configured', 'device': device_id, 'version': firmware_version}"}