# XML Entity Expansion DoS via Billion Laughs in lxml.etree.parse()

Language: Python
Severity: High
CWE: CWE-776

## Source
5

## Flow
5-6

## Sink
6

## Vulnerable Code
```python
from lxml import etree
import io

def process_iot_device_config(xml_payload):
    device_stream = io.BytesIO(xml_payload.encode('utf-8'))
    config_tree = etree.parse(device_stream)
    root_element = config_tree.getroot()
    device_id = root_element.find('.//device_identifier').text
    firmware_ver = root_element.find('.//firmware_version').text
    telemetry_interval = root_element.find('.//telemetry_rate').text
    return {'id': device_id, 'firmware': firmware_ver, 'interval': telemetry_interval}
```

## Explanation

The code uses lxml.etree.parse() without disabling entity expansion, making it vulnerable to XML Entity Expansion (Billion Laughs) attacks. An attacker can send malicious XML with recursive entity definitions that exponentially expand in memory, causing DoS through resource exhaustion.

## Remediation

The fix creates a secure XMLParser instance with resolve_entities=False to prevent entity expansion, no_network=True to block external network access, and load_dtd=False to prevent loading of DTD definitions. This parser is then passed to etree.parse(), ensuring that Billion Laughs and XXE attacks are neutralized by refusing to process entity definitions.

## Secure Code
```python
from lxml import etree
import io

def process_iot_device_config(xml_payload):
    device_stream = io.BytesIO(xml_payload.encode('utf-8'))
    parser = etree.XMLParser(resolve_entities=False, no_network=True, dtd_validation=False, load_dtd=False)
    config_tree = etree.parse(device_stream, parser)
    root_element = config_tree.getroot()
    device_id = root_element.find('.//device_identifier').text
    firmware_ver = root_element.find('.//firmware_version').text
    telemetry_interval = root_element.find('.//telemetry_rate').text
    return {'id': device_id, 'firmware': firmware_ver, 'interval': telemetry_interval}
```
