changeset a64ca55b86e3 in trytond:default
details: https://hg.tryton.org/trytond?cmd=changeset&node=a64ca55b86e3
description:
Protect against XML vulnerabilities
issue11219
issue11244
diffstat:
CHANGELOG | 2 ++
setup.py | 1 +
trytond/__init__.py | 6 ++++++
trytond/ir/translation.py | 4 ++--
trytond/ir/ui/view.py | 2 +-
trytond/model/modelview.py | 3 ++-
trytond/protocols/xmlrpc.py | 3 +++
7 files changed, 17 insertions(+), 4 deletions(-)
diffs (111 lines):
diff -r 3583f192a9ef -r a64ca55b86e3 CHANGELOG
--- a/CHANGELOG Tue Feb 22 23:06:02 2022 +0100
+++ b/CHANGELOG Tue Mar 01 19:07:56 2022 +0100
@@ -1,3 +1,5 @@
+* Do not resolve entities by default with lxml (issue11219)
+* Use defusedxml to parse XML (issue11244)
* Use dictionary as search_order on Reference field
* Retry sending email on temporary failure
* Order not sorted Selection by index definition
diff -r 3583f192a9ef -r a64ca55b86e3 setup.py
--- a/setup.py Tue Feb 22 23:06:02 2022 +0100
+++ b/setup.py Tue Mar 01 19:07:56 2022 +0100
@@ -157,6 +157,7 @@
license='GPL-3',
python_requires='>=3.7',
install_requires=[
+ 'defusedxml',
'lxml >= 2.0',
'relatorio[fodt] >= 0.7.0',
'Genshi',
diff -r 3583f192a9ef -r a64ca55b86e3 trytond/__init__.py
--- a/trytond/__init__.py Tue Feb 22 23:06:02 2022 +0100
+++ b/trytond/__init__.py Tue Mar 01 19:07:56 2022 +0100
@@ -5,6 +5,8 @@
import warnings
from email import charset
+from lxml import etree, objectify
+
__version__ = "6.3.0"
os.environ['TZ'] = 'UTC'
@@ -16,3 +18,7 @@
# set email encoding for utf-8 to 'quoted-printable'
charset.add_charset('utf-8', charset.QP, charset.QP)
+
+# prevent XML vulnerabilities by default
+etree.set_default_parser(etree.XMLParser(resolve_entities=False))
+objectify.set_default_parser(objectify.makeparser(resolve_entities=False))
diff -r 3583f192a9ef -r a64ca55b86e3 trytond/ir/translation.py
--- a/trytond/ir/translation.py Tue Feb 22 23:06:02 2022 +0100
+++ b/trytond/ir/translation.py Tue Mar 01 19:07:56 2022 +0100
@@ -1,12 +1,12 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
import os
-import xml.dom.minidom
from collections import defaultdict
from difflib import SequenceMatcher
from io import BytesIO
import polib
+from defusedxml.minidom import parseString
from genshi.filters.i18n import extract as genshi_extract
from lxml import etree
from relatorio.reporting import MIMETemplateLoader
@@ -958,7 +958,7 @@
zip_.read('content.xml'),
zip_.read('styles.xml'),
]:
- document = xml.dom.minidom.parseString(content_xml)
+ document = parseString(content_xml)
for string in extract(document.documentElement):
yield string
diff -r 3583f192a9ef -r a64ca55b86e3 trytond/ir/ui/view.py
--- a/trytond/ir/ui/view.py Tue Feb 22 23:06:02 2022 +0100
+++ b/trytond/ir/ui/view.py Tue Mar 01 19:07:56 2022 +0100
@@ -241,7 +241,7 @@
])
views.sort(
key=lambda v: self._module_index.get(v.module, -1), reverse=True)
- parser = etree.XMLParser(remove_comments=True)
+ parser = etree.XMLParser(remove_comments=True, resolve_entities=False)
tree = etree.fromstring(arch, parser=parser)
decoder = PYSONDecoder({'context': Transaction().context})
for view in views:
diff -r 3583f192a9ef -r a64ca55b86e3 trytond/model/modelview.py
--- a/trytond/model/modelview.py Tue Feb 22 23:06:02 2022 +0100
+++ b/trytond/model/modelview.py Tue Mar 01 19:07:56 2022 +0100
@@ -250,7 +250,8 @@
level = 1 if result['type'] == 'tree' else 0
# Update arch and compute fields from arch
- parser = etree.XMLParser(remove_blank_text=True)
+ parser = etree.XMLParser(
+ remove_blank_text=True, resolve_entities=False)
tree = etree.fromstring(result['arch'], parser)
result['arch'], result['fields'] = cls.parse_view(
tree, result['type'], view_id=view_id,
diff -r 3583f192a9ef -r a64ca55b86e3 trytond/protocols/xmlrpc.py
--- a/trytond/protocols/xmlrpc.py Tue Feb 22 23:06:02 2022 +0100
+++ b/trytond/protocols/xmlrpc.py Tue Mar 01 19:07:56 2022 +0100
@@ -6,6 +6,7 @@
# convert decimal to float before marshalling:
from decimal import Decimal
+import defusedxml.xmlrpc
from werkzeug.exceptions import (
BadRequest, Conflict, Forbidden, InternalServerError, Locked,
TooManyRequests)
@@ -20,6 +21,8 @@
logger = logging.getLogger(__name__)
+defusedxml.xmlrpc.monkey_patch()
+
def dump_decimal(self, value, write):
write('<value><bigdecimal>')