High severityGHSA Advisory· Published Aug 26, 2025· Updated Sep 29, 2025
xml2rfc has an arbitrary file read vulnerability
CVE-2025-11058
Description
Impact
When generating PDF files, this vulnerability allows an attacker to read arbitrary files from the filesystem by injecting malicious link element into the XML.
Workarounds
Test untrusted input with link elements with rel="attachment" before processing.
Credits
This vulnerability was reported by Mohamed Ouad from Doyensec.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
xml2rfcPyPI | < 3.30.1 | 3.30.1 |
Affected products
1- Range: <= 3.30.0
Patches
1f2b245bc0aeeMerge commit from fork
3 files changed · +46 −1
test.py+33 −0 modified@@ -14,6 +14,7 @@ from xml2rfc.writers.base import default_options, BaseV3Writer, RfcWriterError from xml2rfc.writers import DatatrackerToBibConverter from xml2rfc.writers.text import MAX_WIDTH +from xml2rfc.utils import strip_link_attachments from xml2rfc.util.file import can_access, FileAccessError try: @@ -1069,5 +1070,37 @@ def test_allowed_access_template(self): access_templates=True)) +class StripLinkAttachmentsTest(unittest.TestCase): + def setUp(self): + self.options = copy.deepcopy(default_options) + + def test_strips_attachement(self): + self.options.allow_local_file_access = False + xml_tree = lxml.etree.fromstring(""" +<rfc> + <link rel="item" href="urn:issn:0000-0000" /> + <link rel="attachment" href="/etc/passwd" /> + <link rel="describedBy" href="doi:00.00000/rfc0000" /> + <link rel="prev" href="https://www.ietf.org/archive/id/draft-ietf-empire-death-star-00.txt" /> + <link rel="attachment" href="/home/vader/ds-1/schematics" /> + <link rel="alternate" href="https://www.ietf.org/ds-1" /> +</rfc>""") + + strip_link_attachments(xml_tree) + + # keeps non rel="attachment" elements + for rel in ["item", "describedBy", "prev", "alternate"]: + links = xml_tree.xpath(f'//link[@rel="{rel}"]') + self.assertEqual(len(links), 1) + + # strip rel="attachment" + attachments = xml_tree.xpath('//link[@rel="attachment"]') + self.assertEqual(len(attachments), 0) + xml_str = lxml.etree.tostring(xml_tree).decode() + self.assertNotIn("attachment", xml_str) + self.assertNotIn("/etc/passwd", xml_str) + self.assertNotIn("/home/vader/ds-1/schematics", xml_str) + + if __name__ == '__main__': unittest.main()
xml2rfc/utils.py+9 −0 modified@@ -362,6 +362,15 @@ def find_duplicate_attr_values(attr, tree): seen.add(id) return dups +def strip_link_attachments(tree): + """ + Find link tags with rel="attachment". + """ + for attachment in tree.xpath('//link[@rel="attachment"]'): + xml2rfc.log.warn(f"Removed {attachment}. link relationships type attachment is not allowed.") + attachment.getparent().remove(attachment) + + # ---------------------------------------------------------------------- # Unicode operations
xml2rfc/writers/base.py+4 −1 modified@@ -28,7 +28,7 @@ from xml2rfc.util.file import can_access, FileAccessError from xml2rfc.util.name import short_author_ascii_name_parts, full_author_name_expansion, short_author_name_parts from xml2rfc.util.unicode import is_svg -from xml2rfc.utils import namespaces, find_duplicate_ids, slugify +from xml2rfc.utils import namespaces, find_duplicate_ids, slugify, strip_link_attachments SUBSERIES = { @@ -2117,6 +2117,9 @@ def validate(self, when='', warn=False): # a duplicate xsd:ID attribute. So we check all attributes with # content specified as xsd:ID first, and give better messages: + # Strip link attachments + strip_link_attachments(self.tree) + # Get the attributes we need to check if when and not when.startswith(' '): when = ' '+when
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
3News mentions
0No linked articles in our index yet.