T09 · Insecure Skill Coding Practices
- Location
ooxml/scripts/validation/base.py:127- Finding
Untrusted OOXML Parsed with Unsafe Default lxml Settings
- Content
View full analysis
Vulnerability Details
File Location:
ooxml/scripts/validation/base.py:127, 149, 176, 391, 537, 762-768; equivalent default-parser calls also occur inooxml/scripts/validation/docx.py:85, 129, 167, 189, 212andooxml/scripts/validation/pptx.py:86, 140, 153, 197, 240.Vulnerability Type: Unsafe XML parsing
Risk Level: HighVulnerable Code
python for xml_file in self.xml_files: try: # Try to parse the XML file lxml.etree.parse(str(xml_file)) except lxml.etree.XMLSyntaxError as e: errors.append( f" {xml_file.relative_to(self.unpacked_dir)}: " f"Line {e.lineno}: {e.msg}" )The XSD-validation path similarly creates a parser without security restrictions and then parses document-controlled XML with the default parser:
python # Load schema with open(schema_path, "rb") as xsd_file: parser = lxml.etree.XMLParser() xsd_doc = lxml.etree.parse( xsd_file, parser=parser, base_url=str(schema_path), ) schema = lxml.etree.XMLSchema(xsd_doc) # Load and preprocess XML with open(xml_file) as f: xml_doc = lxml.etree.parse(f)Technical Analysis
The validation code processes XML extracted from user-supplied DOCX and PPTX packages. It uses default
lxml.etreeparsing behavior without explicitly disabling DTD loading, external entity resolution, or network access.This creates an XML External Entity and entity-expansion attack surface. Depending on the installed
lxml/libxml2 version and parser behavior, crafted entity declarations may cause local resources to be read during parsing or may consume substantial CPU and memory. The project already usesdefusedxmlin other components, demonstrating that safer parsing is available but is not applied consistently.The parser is invoked repeatedly across several validation passes, potentially multiplying the resource impact of one malicious XML part.
Attack Path
- An attacker ...[truncated 1173 chars]
- Remediation
View remediation
Remediation Suggestions
- Create one hardened parser factory and use it for every untrusted XML parse:
python def secure_xml_parser(): return lxml.etree.XMLParser( resolve_entities=False, load_dtd=False, no_network=True, huge_tree=False, recover=False, )- Pass the hardened parser explicitly:
python root = lxml.etree.parse( str(xml_file), parser=secure_xml_parser(), ).getroot()- Reject document XML containing DTD or entity declarations before validation.
- Prefer
defusedxmlwhere advancedlxmlfunctionality is unnecessary. - Apply the same restrictions in
base.py,docx.py, andpptx.py. - Add input-size, tree-depth, element-count, attribute-count, and text-length limits.
- Run document parsing in a sandbox with restricted filesystem access, memory limits, CPU limits, and no network access.
- Add regression tests using external-entity payloads and entity-expansion payloads.
