Skip to content

fix: [import_mod/lib] use defusedxml for GoAML and ODT parsing - #871

Open
elhoim wants to merge 1 commit into
MISP:mainfrom
elhoim:fix/061-defusedxml-parse
Open

fix: [import_mod/lib] use defusedxml for GoAML and ODT parsing#871
elhoim wants to merge 1 commit into
MISP:mainfrom
elhoim:fix/061-defusedxml-parse

Conversation

@elhoim

@elhoim elhoim commented Aug 31, 2026

Copy link
Copy Markdown
Member

The defect

Both goamlimport.py and odtreader.py parse attacker-supplied XML with the standard library's xml.etree.ElementTree, which is not hardened against XML entity-expansion attacks:

# misp_modules/modules/import_mod/goamlimport.py:251
self.tree = ET.fromstring(data)

# misp_modules/lib/ODTReader/odtreader.py:31
root = ET.fromstring(odtContent)

xml.etree.ElementTree.fromstring will happily expand nested internal entities (e.g. "billion laughs") or resolve external entities, so a crafted GoAML report or a crafted content.xml inside an .odt file can exhaust memory/CPU on the misp-modules worker.

Impact

A MISP user importing a malicious GoAML report or a malicious .odt file (both are user-supplied import inputs) can cause a denial-of-service against the misp-modules server process handling the import — no authentication beyond "can submit an import" is required.

Fix

Swap the import to defusedxml.ElementTree, which rejects entity expansion and external entity resolution while preserving the same fromstring API used at both call sites (ET.fromstring only — no other ET.* attributes are used in either file, so this is a drop-in replacement here). No behaviour change for well-formed, non-malicious input.

defusedxml (0.7.1) is already present in poetry.lock as a transitive dependency of sigmf, so no new dependency is introduced by this change — only the import is swapped. It is not currently declared as a direct dependency in pyproject.toml; maintainers may want to promote it to a direct dependency now that the code relies on it explicitly rather than transitively.

Verification

  • flake8 clean on goamlimport.py; py_compile clean on odtreader.py.
  • Full module test suite: 161 passed, 4 skipped, 5 subtests passed in 24.63s.
  • Confirmed both files use only ET.fromstring (grep -n 'ET\.' ...), which defusedxml.ElementTree supports directly.

Found during a review of the repository; other findings are being submitted as separate PRs.

🤖 Generated with Claude Code

https://claude.ai/code/session_018dfYpyaSZd1nxSRLr8suj8

goamlimport.py and lib/ODTReader/odtreader.py both parse attacker-supplied
files with the stdlib xml.etree.ElementTree.fromstring, which is not
hardened against XML entity-expansion attacks such as billion-laughs. A
crafted GoAML XML report or .odt document submitted for import can exhaust
memory or CPU on the MISP server through nested entity expansion, turning
a routine import into a denial of service. defusedxml is already pulled in
via the sigmf dependency in poetry.lock, so swap both fromstring calls to
use defusedxml.ElementTree instead of the stdlib module.

Verified with flake8 on goamlimport.py and py_compile on odtreader.py
(both clean), and the full pytest suite against a live modules server on
port 6761: 161 passed, 4 skipped, 5 subtests passed, matching baseline.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018dfYpyaSZd1nxSRLr8suj8
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant