security: use defusedxml to protect against XML attacks - #4094
Merged
tonioo merged 1 commit intoJul 10, 2026
Conversation
Replace unsafe xml.etree.ElementTree with defusedxml.ElementTree in autoconfig/views.py to block entity expansion (XXE) and other XML decoding attacks. For carddav.py, configure lxml with a hardened XMLParser (resolve_entities=False, no_network=True) since defusedxml.lxml is deprecated. defusedxml is already a dependency (used in dmarc/lib.py) so no new packages are required. Tests added: - autoconfig: XXE entity in EMailAddress is not resolved (404) - carddav: entity expansion blocked, valid XML still parses
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #4094 +/- ##
==========================================
+ Coverage 84.42% 84.43% +0.01%
==========================================
Files 324 324
Lines 16382 16385 +3
Branches 2183 2183
==========================================
+ Hits 13830 13835 +5
+ Misses 1840 1838 -2
Partials 712 712 🚀 New features to boost your workflow:
|
tonioo
approved these changes
Jul 10, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Closes #1556
This PR replaces unsafe XML parsing with hardened equivalents to protect against XXE (XML External Entity), billion laughs, and other XML decoding attacks.
Changes
modoboa/autoconfig/views.pyimport xml.etree.ElementTree as ETwithfrom defusedxml.ElementTree import fromstring_email_address_from_xml_body()function parses Outlook Autodiscover XML from untrusted HTTP POST bodies — this is a direct attack surfaceParseError(malformed XML) andValueError(defusedxml security exceptions likeEntitiesForbidden,DTDFForbidden)modoboa/contacts/lib/carddav.py_SECURE_PARSER = ET.XMLParser(resolve_entities=False, no_network=True)and a_safe_xml()wrapperET.XML(xml)calls (in__process_report_resultand_process_xml_props) with_safe_xml(xml)defusedxml.lxml(which is deprecated and will be removed in a future release)Why not defusedxml.lxml?
defusedxml.lxmlis deprecated per its own documentation. The lxml-recommended approach is to configureXMLParserwithresolve_entities=Falseandno_network=True, which provides the same protections while keeping full lxml API compatibility (the code relies oniterchildren()/iterdescendants()which are lxml-specific).No new dependencies
defusedxmlis already listed inpyproject.toml(defusedxml>=0.6.0) and is already used inmodoboa/dmarc/lib.py.Tests
modoboa/autoconfig/tests.pytest_autodiscover_xxe_entity_not_resolved: POSTs an XML body with a<!ENTITY>declaration insideEMailAddress— verifies the entity is not resolved and the response is 404modoboa/contacts/tests.pyCardDavSecurityTestCase.test_safe_xml_rejects_entity_expansion: verifies&xxe;entity reference is not expanded (text is None)CardDavSecurityTestCase.test_safe_xml_parses_valid_document: verifies valid DAV XML still parses correctly with the secure parser