# XML External Entity (XXE) via xml.dom.minidom.parse on Untrusted XML

Language: Python
Severity: High
CWE: CWE-611

## Source
1

## Flow
1-3-4-5

## Sink
5

## Vulnerable Code
```python
from xml.dom import minidom
import os

def process_iot_device_telemetry(telemetry_xml_data):
    temp_file = f"/tmp/telemetry_{os.getpid()}.xml"
    with open(temp_file, 'w') as f:
        f.write(telemetry_xml_data)
    parsed_doc = minidom.parse(temp_file)
    device_id = parsed_doc.getElementsByTagName('deviceId')[0].firstChild.data
    temperature = parsed_doc.getElementsByTagName('temp')[0].firstChild.data
    humidity = parsed_doc.getElementsByTagName('humidity')[0].firstChild.data
    os.remove(temp_file)
    return {'device': device_id, 'temp': temperature, 'humidity': humidity}
```

## Explanation

The function accepts untrusted XML telemetry data as input (telemetry_xml_data parameter) and parses it using xml.dom.minidom.parse() without disabling external entity processing. This allows an attacker to inject malicious XML with external entity references that can read local files, perform SSRF attacks, or cause denial of service.

## Remediation

The fix replaces the vulnerable xml.dom.minidom.parse() with defusedxml.minidom.parseString(), which automatically disables external entity processing, DTD retrieval, and other dangerous XML features. Additionally, the unnecessary temporary file creation pattern was removed by parsing the XML string directly, eliminating both the XXE vulnerability and potential file system race conditions.

## Secure Code
```python
from defusedxml.minidom import parseString
import os

def process_iot_device_telemetry(telemetry_xml_data):
    parsed_doc = parseString(telemetry_xml_data)
    device_id = parsed_doc.getElementsByTagName('deviceId')[0].firstChild.data
    temperature = parsed_doc.getElementsByTagName('temp')[0].firstChild.data
    humidity = parsed_doc.getElementsByTagName('humidity')[0].firstChild.data
    return {'device': device_id, 'temp': temperature, 'humidity': humidity}
```
