diff --git a/CHANGELOG.md b/CHANGELOG.md index a85de73..7182af3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,10 @@ +0.11.0 (2024-02-xx) +------------------- + +- security fix: escaped HTML entities like `>` were unescaped in the final mjml output, leading to potential injection of untrusted user data (reported by @sh-at-cs) + + 0.10.0 (2023-11-17) ------------------ diff --git a/mjml/elements/head/mj_style.py b/mjml/elements/head/mj_style.py index c1e4ed4..1da2024 100644 --- a/mjml/elements/head/mj_style.py +++ b/mjml/elements/head/mj_style.py @@ -10,10 +10,15 @@ class MjStyle(HeadComponent): @classmethod def default_attrs(cls): return { - 'inline' : '', + 'inline': '', } def handler(self): add = self.context['add'] inline_attr = 'inlineStyle' if (self.get_attr('inline') == 'inline') else 'style' - add(inline_attr, self.getContent()) + html_str = self.getContent() + # CSS can contain child selectors (e.g. "h1 > p") beautifulsoup only + # returns escaped entities. To make these selectors work, we need to + # unescape these. + css_str = html_str.replace('>', '>') + add(inline_attr, css_str) diff --git a/mjml/mjml2html.py b/mjml/mjml2html.py index 8c542b6..cbef123 100644 --- a/mjml/mjml2html.py +++ b/mjml/mjml2html.py @@ -116,7 +116,7 @@ def parse(_mjml, parentMjClass='', *, template_dir): classes = ignore_empty(attributes.get('mj-class', '').split(' ')) # upstream parses text contents (+ comments) in mjml-parser-xml/index.js - content = _mjml.decode_contents(formatter=None) + content = _mjml.decode_contents() attributesClasses = {} for css_class in classes: @@ -213,7 +213,7 @@ def _head_data_add(attr, *params): for element in contentSoup.select(selector): element[attrName] = value or '' - content = contentSoup.decode_contents(formatter=None) + content = contentSoup.decode_contents() content = skeleton( content=content, diff --git a/tests/testdata/mj-text-escaped-html-expected.html b/tests/testdata/mj-text-escaped-html-expected.html new file mode 100644 index 0000000..8cbc319 --- /dev/null +++ b/tests/testdata/mj-text-escaped-html-expected.html @@ -0,0 +1,120 @@ + + + +
+
+
+
+
+
+
|
+