microsoft / microsoft/markitdown

Security: XXE vulnerability in DOCX pre-processor (ET.fromstring on untrusted input)

Open
#1,565 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
186k
Forks
13.7k
Avg merge
1d 4h
Merged PRs (30d)
49

Description

Security Vulnerability Report

Type: XML External Entity (XXE) Injection
Severity: High
File: packages/markitdown/src/markitdown/converter_utils/docx/pre_process.py, line 45
Commit tested: 4a5340f93b2bf1dc11641f921fbfd6d5f016924b

Description

The function _convert_omath_to_latex() in pre_process.py uses ET.fromstring() to parse XML content extracted from user-supplied DOCX files:

math_root = ET.fromstring(MATH_ROOT_TEMPLATE.format(str(tag)))

The tag variable originates from BeautifulSoup parsing of the DOCX document.xml, which is user-supplied content. A DOCX file is a ZIP archive containing XML — an attacker can craft a DOCX with malicious Office Math Markup (OMML) tags containing XML external entity declarations.

Python's xml.etree.ElementTree is documented as "not secure against maliciously constructed data". While CPython's expat-based parser has limited XXE surface compared to lxml, it is still vulnerable to:

  • Billion Laughs (exponential entity expansion) causing denial of service
  • External entity resolution depending on parser configuration
  • DTD processing attacks
Secondary Finding (Medium)

Unvalidated exiftool_path parameter reaching subprocess.run() in packages/markitdown/src/markitdown/converters/_exiftool.py (lines 22 and 41). While this uses list-style invocation (not shell=True), the path is not validated against path traversal or symlink attacks.

Recommended Fix

For the XXE:

# Replace:
from xml.etree import ElementTree as ET

# With:
import defusedxml.ElementTree as ET

Or call defusedxml.defuse_stdlib() at module initialization.

For the subprocess issue:

  • Validate exiftool_path against an allowlist or verify it resolves to a known binary using shutil.which()
Impact

markitdown is widely used for converting documents to Markdown. Any application processing untrusted DOCX files is potentially vulnerable, including:

  • Web services accepting document uploads
  • CI/CD pipelines processing documentation
  • AI/LLM pipelines using markitdown for document ingestion
  • The markitdown MCP server (markitdown-mcp)
Disclosure Process

We attempted to report this through secure@microsoft.com (bounced — no longer accepted) and the MSRC Researcher Portal. This issue was discovered during an automated scan using the Colosseum deep code analysis platform — 51 gauntlets × 2 platforms × 7 rounds, with 98% cross-platform agreement.

Full scan report: https://battleharden.dev/reports/markitdown

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with packages/markitdown/src/markitdown/converter_utils/docx/pre_process.py and inspect _convert_omath_to_latex(), especially the ET.fromstring() call, then review packages/markitdown/src/markitdown/converters/_exiftool.py and its subprocess calls. Confirm the handling of crafted DOCX XML and exiftool_path inputs, add regression coverage for the reported cases, and verify the security tests pass.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.