Typing stubs for defusedxml
types-defusedxml provides type hints for the defusedxml library, which offers protection against XML-related security vulnerabilities like XML bombs (Billion Laughs, Quadratic Blowup) and external entity attacks in Python's standard library XML modules. It is part of the typeshed project and allows type checkers to analyze code using defusedxml for correctness. This package ensures compatibility with defusedxml==0.7.* and is regularly updated.
Warnings
- gotcha Stub-only package: `types-defusedxml` is solely for static type checking and contains no runtime code. To utilize `defusedxml` functionality, the `defusedxml` package must also be installed in your environment (`pip install defusedxml`).
- gotcha Version Mismatches: Type stubs in typeshed are updated frequently. While `types-defusedxml` aims to provide accurate annotations for `defusedxml==0.7.*`, mismatches between the stub version and the runtime `defusedxml` version can lead to incorrect type-checking results, especially if `defusedxml`'s API changes.
- deprecated The `defusedxml.lxml` module is deprecated within `defusedxml` and is slated for removal in future releases. `lxml` itself has built-in mitigations for many XML attacks (e.g., billion laughs, quadratic blowup).
- breaking Changes from Typeshed: Although typeshed strives to minimize breaking changes, any update to stub packages can potentially introduce changes that might cause your code to fail type-checking. This can occur if the underlying library's API has changed or if the stubs become more restrictive in their type definitions.
Install
-
pip install types-defusedxml -
pip install defusedxml
Imports
- ElementTree
import defusedxml.ElementTree as ET
- fromstring
from defusedxml.ElementTree import fromstring
- parse
from defusedxml.ElementTree import parse
- minidom
import defusedxml.minidom as minidom
- sax
import defusedxml.sax as sax
- lxml
import defusedxml.lxml
Quickstart
import defusedxml.ElementTree as ET
from typing import Dict, Any
xml_data_safe = "<root><item>safe_data</item></root>"
xml_data_malicious = """
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM \"file:///non_existent_path\" >
]>
<foo>&xxe;</foo>
"""
def parse_xml_safely(xml_string: str) -> Dict[str, Any]:
try:
# types-defusedxml provides type hints for ET.fromstring
root = ET.fromstring(xml_string)
result = {child.tag: child.text for child in root}
print(f"Successfully parsed: {result}")
return result
except ET.EntitiesForbidden as e:
print(f"Caught an XML entity expansion attempt: {e}")
return {"error": "Entities Forbidden"}
except ET.ParseError as e:
print(f"Caught a general XML parsing error: {e}")
return {"error": "Parse Error"}
# Example usage with safe data
parse_xml_safely(xml_data_safe)
# Example usage with malicious data (XXE attempt)
# This should be blocked by defusedxml, with stubs informing type checkers
# about the EntitiesForbidden exception.
parse_xml_safely(xml_data_malicious)