# XML External Entity (XXE) via unsafe XML parser configuration

Language: Python
Severity: High
CWE: CWE-611

## Source
5

## Flow
5-8

## Sink
8

## Vulnerable Code
```python
import lxml.etree as etree
from flask import request, jsonify

def process_iot_device_telemetry():
    device_xml = request.data
    parser = etree.XMLParser(resolve_entities=True, no_network=False)
    try:
        telemetry_doc = etree.fromstring(device_xml, parser)
        device_id = telemetry_doc.find('.//deviceId').text
        temperature = telemetry_doc.find('.//temperature').text
        humidity = telemetry_doc.find('.//humidity').text
        return jsonify({'status': 'success', 'device': device_id, 'temp': temperature, 'humidity': humidity})
    except Exception as e:
        return jsonify({'error': 'Telemetry parsing failed', 'details': str(e)}), 400
```

## Explanation

The code accepts untrusted XML data from the HTTP request body and parses it using lxml with resolve_entities=True and no_network=False, enabling XXE attacks. An attacker can inject malicious XML with external entity declarations to read local files, perform SSRF attacks, or cause denial of service.

## Remediation

The fix disables XML external entity resolution by setting resolve_entities=False and no_network=True, preventing the parser from loading external entities or making network requests. Additionally, dtd_validation=False and load_dtd=False are set to prevent DTD-based attacks entirely.

## Secure Code
```python
import lxml.etree as etree
from flask import request, jsonify

def process_iot_device_telemetry():
    device_xml = request.data
    parser = etree.XMLParser(resolve_entities=False, no_network=True, dtd_validation=False, load_dtd=False)
    try:
        telemetry_doc = etree.fromstring(device_xml, parser)
        device_id = telemetry_doc.find('.//deviceId').text
        temperature = telemetry_doc.find('.//temperature').text
        humidity = telemetry_doc.find('.//humidity').text
        return jsonify({'status': 'success', 'device': device_id, 'temp': temperature, 'humidity': humidity})
    except Exception as e:
        return jsonify({'error': 'Telemetry parsing failed', 'details': str(e)}), 400
```
