Control: tags 986251 + patch
Control: tags 986251 + pending

Dear maintainer,

I've prepared an NMU for python-bleach (versioned as 3.2.1-2.1) and
uploaded it to DELAYED/5. Please feel free to tell me if I
should delay it longer.

Actually if you want to take care of it that would be the preferable
option, or if you think this is fine and inline in how you would like
to have we can have it reschduled as well, so that the unblock can be
asked earlier.

The fix should in any case ideally go to bullseye.

Regards,
Salvatore
diff -Nru python-bleach-3.2.1/debian/changelog python-bleach-3.2.1/debian/changelog
--- python-bleach-3.2.1/debian/changelog	2021-01-18 07:30:51.000000000 +0100
+++ python-bleach-3.2.1/debian/changelog	2021-04-03 17:17:55.000000000 +0200
@@ -1,3 +1,11 @@
+python-bleach (3.2.1-2.1) unstable; urgency=medium
+
+  * Non-maintainer upload.
+  * sanitizer: escape HTML comments (CVE-2021-23980) (Closes: #986251)
+  * tests: add tests for more eject tags for GHSA-vv2x-vrpj-qqpq
+
+ -- Salvatore Bonaccorso <car...@debian.org>  Sat, 03 Apr 2021 17:17:55 +0200
+
 python-bleach (3.2.1-2) unstable; urgency=medium
 
   * Team upload.
diff -Nru python-bleach-3.2.1/debian/patches/0004-sanitizer-escape-HTML-comments.patch python-bleach-3.2.1/debian/patches/0004-sanitizer-escape-HTML-comments.patch
--- python-bleach-3.2.1/debian/patches/0004-sanitizer-escape-HTML-comments.patch	1970-01-01 01:00:00.000000000 +0100
+++ python-bleach-3.2.1/debian/patches/0004-sanitizer-escape-HTML-comments.patch	2021-04-03 17:17:22.000000000 +0200
@@ -0,0 +1,95 @@
+From: Greg Guthe <ggu...@mozilla.com>
+Date: Thu, 28 Jan 2021 14:56:24 -0500
+Subject: sanitizer: escape HTML comments
+Origin: https://github.com/mozilla/bleach/commit/1334134d34397966a7f7cfebd38639e9ba2c680e
+Bug-Debian: https://bugs.debian.org/986251
+Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1689399
+Bug: https://github.com/mozilla/bleach/security/advisories/GHSA-vv2x-vrpj-qqpq
+Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2021-23980
+
+fixes: bug 1689399 / GHSA vv2x-vrpj-qqpq
+---
+ bleach/html5lib_shim.py |  1 +
+ bleach/sanitizer.py     |  4 ++++
+ tests/test_clean.py     | 47 +++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 52 insertions(+)
+
+--- a/bleach/html5lib_shim.py
++++ b/bleach/html5lib_shim.py
+@@ -48,6 +48,7 @@ from html5lib._inputstream import (
+     HTMLInputStream,
+ )  # noqa: E402 module level import not at top of file
+ from html5lib.serializer import (
++    escape,
+     HTMLSerializer,
+ )  # noqa: E402 module level import not at top of file
+ from html5lib._tokenizer import (
+--- a/bleach/sanitizer.py
++++ b/bleach/sanitizer.py
+@@ -376,6 +376,10 @@ class BleachSanitizerFilter(html5lib_shi
+ 
+         elif token_type == "Comment":
+             if not self.strip_html_comments:
++                # call lxml.sax.saxutils to escape &, <, and > in addition to " and '
++                token["data"] = html5lib_shim.escape(
++                    token["data"], entities={'"': "&quot;", "'": "&#x27;"}
++                )
+                 return token
+             else:
+                 return None
+--- a/tests/test_clean.py
++++ b/tests/test_clean.py
+@@ -766,6 +766,53 @@ def test_namespace_rc_data_element_strip
+     )
+ 
+ 
++@pytest.mark.parametrize(
++    "namespace_tag, end_tag, data, expected",
++    [
++        (
++            "math",
++            "p",
++            "<math></p><style><!--</style><img src/onerror=alert(1)>",
++            "<math><p></p><style><!--&lt;/style&gt;&lt;img src/onerror=alert(1)&gt;--></style></math>",
++        ),
++        (
++            "math",
++            "br",
++            "<math></br><style><!--</style><img src/onerror=alert(1)>",
++            "<math><br><style><!--&lt;/style&gt;&lt;img src/onerror=alert(1)&gt;--></style></math>",
++        ),
++        (
++            "svg",
++            "p",
++            "<svg></p><style><!--</style><img src/onerror=alert(1)>",
++            "<svg><p></p><style><!--&lt;/style&gt;&lt;img src/onerror=alert(1)&gt;--></style></svg>",
++        ),
++        (
++            "svg",
++            "br",
++            "<svg></br><style><!--</style><img src/onerror=alert(1)>",
++            "<svg><br><style><!--&lt;/style&gt;&lt;img src/onerror=alert(1)&gt;--></style></svg>",
++        ),
++    ],
++)
++def test_html_comments_escaped(namespace_tag, end_tag, data, expected):
++    # refs: bug 1689399 / GHSA-vv2x-vrpj-qqpq
++    #
++    # p and br can be just an end tag (e.g. </p> == <p></p>)
++    #
++    # In browsers:
++    #
++    # * img and other tags break out of the svg or math namespace (e.g. <svg><img></svg> == <svg><img></svg>)
++    # * style does not (e.g. <svg><style></svg> == <svg><style></style></svg>)
++    # * the breaking tag ejects trailing elements (e.g. <svg><img><style></style></svg> == <svg></svg><img><style></style>)
++    #
++    # the ejected elements can trigger XSS
++    assert (
++        clean(data, tags=[namespace_tag, end_tag, "style"], strip_comments=False)
++        == expected
++    )
++
++
+ def get_ids_and_tests():
+     """Retrieves regression tests from data/ directory
+ 
diff -Nru python-bleach-3.2.1/debian/patches/0005-tests-add-tests-for-more-eject-tags-for-GHSA-vv2x-vr.patch python-bleach-3.2.1/debian/patches/0005-tests-add-tests-for-more-eject-tags-for-GHSA-vv2x-vr.patch
--- python-bleach-3.2.1/debian/patches/0005-tests-add-tests-for-more-eject-tags-for-GHSA-vv2x-vr.patch	1970-01-01 01:00:00.000000000 +0100
+++ python-bleach-3.2.1/debian/patches/0005-tests-add-tests-for-more-eject-tags-for-GHSA-vv2x-vr.patch	2021-04-03 16:58:05.000000000 +0200
@@ -0,0 +1,309 @@
+From: Greg Guthe <ggu...@mozilla.com>
+Date: Tue, 2 Feb 2021 11:13:09 -0500
+Subject: tests: add tests for more eject tags for GHSA-vv2x-vrpj-qqpq
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+Origin: https://github.com/mozilla/bleach/commit/d398c89e54ced6b1039d3677689707456ba42dec
+
+reported by Micha?? Bentkowski at Securitum
+---
+ tests/test_clean.py | 244 +++++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 241 insertions(+), 3 deletions(-)
+
+diff --git a/tests/test_clean.py b/tests/test_clean.py
+index 7c5657503706..0b7570c76ad2 100644
+--- a/tests/test_clean.py
++++ b/tests/test_clean.py
+@@ -740,35 +740,272 @@ def test_namespace_rc_data_element_strip_false(
+ 
+ 
+ @pytest.mark.parametrize(
+-    "namespace_tag, end_tag, data, expected",
++    "namespace_tag, end_tag, eject_tag, data, expected",
+     [
++        # eject with style
+         (
+             "math",
+             "p",
++            "style",
+             "<math></p><style><!--</style><img src/onerror=alert(1)>",
+             "<math><p></p><style><!--&lt;/style&gt;&lt;img src/onerror=alert(1)&gt;--></style></math>",
+         ),
+         (
+             "math",
+             "br",
++            "style",
+             "<math></br><style><!--</style><img src/onerror=alert(1)>",
+             "<math><br><style><!--&lt;/style&gt;&lt;img src/onerror=alert(1)&gt;--></style></math>",
+         ),
+         (
+             "svg",
+             "p",
++            "style",
+             "<svg></p><style><!--</style><img src/onerror=alert(1)>",
+             "<svg><p></p><style><!--&lt;/style&gt;&lt;img src/onerror=alert(1)&gt;--></style></svg>",
+         ),
+         (
+             "svg",
+             "br",
++            "style",
+             "<svg></br><style><!--</style><img src/onerror=alert(1)>",
+             "<svg><br><style><!--&lt;/style&gt;&lt;img src/onerror=alert(1)&gt;--></style></svg>",
+         ),
++        # eject with title
++        (
++            "math",
++            "p",
++            "title",
++            "<math></p><title><!--</title><img src/onerror=alert(1)>",
++            "<math><p></p><title><!--&lt;/title&gt;&lt;img src/onerror=alert(1)&gt;--></title></math>",
++        ),
++        (
++            "math",
++            "br",
++            "title",
++            "<math></br><title><!--</title><img src/onerror=alert(1)>",
++            "<math><br><title><!--&lt;/title&gt;&lt;img src/onerror=alert(1)&gt;--></title></math>",
++        ),
++        (
++            "svg",
++            "p",
++            "title",
++            "<svg></p><title><!--</title><img src/onerror=alert(1)>",
++            "<svg><p></p><title><!--&lt;/title&gt;&lt;img src/onerror=alert(1)&gt;--></title></svg>",
++        ),
++        (
++            "svg",
++            "br",
++            "title",
++            "<svg></br><title><!--</title><img src/onerror=alert(1)>",
++            "<svg><br><title><!--&lt;/title&gt;&lt;img src/onerror=alert(1)&gt;--></title></svg>",
++        ),
++        # eject with noscript
++        (
++            "math",
++            "p",
++            "noscript",
++            "<math></p><noscript><!--</noscript><img src/onerror=alert(1)>",
++            "<math><p></p><noscript><!--&lt;/noscript&gt;&lt;img src/onerror=alert(1)&gt;--></noscript></math>",
++        ),
++        (
++            "math",
++            "br",
++            "noscript",
++            "<math></br><noscript><!--</noscript><img src/onerror=alert(1)>",
++            "<math><br><noscript><!--&lt;/noscript&gt;&lt;img src/onerror=alert(1)&gt;--></noscript></math>",
++        ),
++        (
++            "svg",
++            "p",
++            "noscript",
++            "<svg></p><noscript><!--</noscript><img src/onerror=alert(1)>",
++            "<svg><p></p><noscript><!--&lt;/noscript&gt;&lt;img src/onerror=alert(1)&gt;--></noscript></svg>",
++        ),
++        (
++            "svg",
++            "br",
++            "noscript",
++            "<svg></br><noscript><!--</noscript><img src/onerror=alert(1)>",
++            "<svg><br><noscript><!--&lt;/noscript&gt;&lt;img src/onerror=alert(1)&gt;--></noscript></svg>",
++        ),
++        # eject with script
++        (
++            "math",
++            "p",
++            "script",
++            "<math></p><script><!--</script><img src/onerror=alert(1)>",
++            "<math><p></p><script><!--&lt;/script&gt;&lt;img src/onerror=alert(1)&gt;--></script></math>",
++        ),
++        (
++            "math",
++            "br",
++            "script",
++            "<math></br><script><!--</script><img src/onerror=alert(1)>",
++            "<math><br><script><!--&lt;/script&gt;&lt;img src/onerror=alert(1)&gt;--></script></math>",
++        ),
++        (
++            "svg",
++            "p",
++            "script",
++            "<svg></p><script><!--</script><img src/onerror=alert(1)>",
++            "<svg><p></p><script><!--&lt;/script&gt;&lt;img src/onerror=alert(1)&gt;--></script></svg>",
++        ),
++        (
++            "svg",
++            "br",
++            "script",
++            "<svg></br><script><!--</script><img src/onerror=alert(1)>",
++            "<svg><br><script><!--&lt;/script&gt;&lt;img src/onerror=alert(1)&gt;--></script></svg>",
++        ),
++        # eject with noembed
++        (
++            "math",
++            "p",
++            "noembed",
++            "<math></p><noembed><!--</noembed><img src/onerror=alert(1)>",
++            "<math><p></p><noembed><!--&lt;/noembed&gt;&lt;img src/onerror=alert(1)&gt;--></noembed></math>",
++        ),
++        (
++            "math",
++            "br",
++            "noembed",
++            "<math></br><noembed><!--</noembed><img src/onerror=alert(1)>",
++            "<math><br><noembed><!--&lt;/noembed&gt;&lt;img src/onerror=alert(1)&gt;--></noembed></math>",
++        ),
++        (
++            "svg",
++            "p",
++            "noembed",
++            "<svg></p><noembed><!--</noembed><img src/onerror=alert(1)>",
++            "<svg><p></p><noembed><!--&lt;/noembed&gt;&lt;img src/onerror=alert(1)&gt;--></noembed></svg>",
++        ),
++        (
++            "svg",
++            "br",
++            "noembed",
++            "<svg></br><noembed><!--</noembed><img src/onerror=alert(1)>",
++            "<svg><br><noembed><!--&lt;/noembed&gt;&lt;img src/onerror=alert(1)&gt;--></noembed></svg>",
++        ),
++        # eject with textarea
++        (
++            "math",
++            "p",
++            "textarea",
++            "<math></p><textarea><!--</textarea><img src/onerror=alert(1)>",
++            "<math><p></p><textarea><!--&lt;/textarea&gt;&lt;img src/onerror=alert(1)&gt;--></textarea></math>",
++        ),
++        (
++            "math",
++            "br",
++            "textarea",
++            "<math></br><textarea><!--</textarea><img src/onerror=alert(1)>",
++            "<math><br><textarea><!--&lt;/textarea&gt;&lt;img src/onerror=alert(1)&gt;--></textarea></math>",
++        ),
++        (
++            "svg",
++            "p",
++            "textarea",
++            "<svg></p><textarea><!--</textarea><img src/onerror=alert(1)>",
++            "<svg><p></p><textarea><!--&lt;/textarea&gt;&lt;img src/onerror=alert(1)&gt;--></textarea></svg>",
++        ),
++        (
++            "svg",
++            "br",
++            "textarea",
++            "<svg></br><textarea><!--</textarea><img src/onerror=alert(1)>",
++            "<svg><br><textarea><!--&lt;/textarea&gt;&lt;img src/onerror=alert(1)&gt;--></textarea></svg>",
++        ),
++        # eject with noframes
++        (
++            "math",
++            "p",
++            "noframes",
++            "<math></p><noframes><!--</noframes><img src/onerror=alert(1)>",
++            "<math><p></p><noframes><!--&lt;/noframes&gt;&lt;img src/onerror=alert(1)&gt;--></noframes></math>",
++        ),
++        (
++            "math",
++            "br",
++            "noframes",
++            "<math></br><noframes><!--</noframes><img src/onerror=alert(1)>",
++            "<math><br><noframes><!--&lt;/noframes&gt;&lt;img src/onerror=alert(1)&gt;--></noframes></math>",
++        ),
++        (
++            "svg",
++            "p",
++            "noframes",
++            "<svg></p><noframes><!--</noframes><img src/onerror=alert(1)>",
++            "<svg><p></p><noframes><!--&lt;/noframes&gt;&lt;img src/onerror=alert(1)&gt;--></noframes></svg>",
++        ),
++        (
++            "svg",
++            "br",
++            "noframes",
++            "<svg></br><noframes><!--</noframes><img src/onerror=alert(1)>",
++            "<svg><br><noframes><!--&lt;/noframes&gt;&lt;img src/onerror=alert(1)&gt;--></noframes></svg>",
++        ),
++        # eject with iframe
++        (
++            "math",
++            "p",
++            "iframe",
++            "<math></p><iframe><!--</iframe><img src/onerror=alert(1)>",
++            "<math><p></p><iframe><!--&lt;/iframe&gt;&lt;img src/onerror=alert(1)&gt;--></iframe></math>",
++        ),
++        (
++            "math",
++            "br",
++            "iframe",
++            "<math></br><iframe><!--</iframe><img src/onerror=alert(1)>",
++            "<math><br><iframe><!--&lt;/iframe&gt;&lt;img src/onerror=alert(1)&gt;--></iframe></math>",
++        ),
++        (
++            "svg",
++            "p",
++            "iframe",
++            "<svg></p><iframe><!--</iframe><img src/onerror=alert(1)>",
++            "<svg><p></p><iframe><!--&lt;/iframe&gt;&lt;img src/onerror=alert(1)&gt;--></iframe></svg>",
++        ),
++        (
++            "svg",
++            "br",
++            "iframe",
++            "<svg></br><iframe><!--</iframe><img src/onerror=alert(1)>",
++            "<svg><br><iframe><!--&lt;/iframe&gt;&lt;img src/onerror=alert(1)&gt;--></iframe></svg>",
++        ),
++        # eject with xmp
++        (
++            "math",
++            "p",
++            "xmp",
++            "<math></p><xmp><!--</xmp><img src/onerror=alert(1)>",
++            "<math><p></p><xmp><!--&lt;/xmp&gt;&lt;img src/onerror=alert(1)&gt;--></xmp></math>",
++        ),
++        (
++            "math",
++            "br",
++            "xmp",
++            "<math></br><xmp><!--</xmp><img src/onerror=alert(1)>",
++            "<math><br><xmp><!--&lt;/xmp&gt;&lt;img src/onerror=alert(1)&gt;--></xmp></math>",
++        ),
++        (
++            "svg",
++            "p",
++            "xmp",
++            "<svg></p><xmp><!--</xmp><img src/onerror=alert(1)>",
++            "<svg><p></p><xmp><!--&lt;/xmp&gt;&lt;img src/onerror=alert(1)&gt;--></xmp></svg>",
++        ),
++        (
++            "svg",
++            "br",
++            "xmp",
++            "<svg></br><xmp><!--</xmp><img src/onerror=alert(1)>",
++            "<svg><br><xmp><!--&lt;/xmp&gt;&lt;img src/onerror=alert(1)&gt;--></xmp></svg>",
++        ),
+     ],
+ )
+-def test_html_comments_escaped(namespace_tag, end_tag, data, expected):
++def test_html_comments_escaped(namespace_tag, end_tag, eject_tag, data, expected):
+     # refs: bug 1689399 / GHSA-vv2x-vrpj-qqpq
+     #
+     # p and br can be just an end tag (e.g. </p> == <p></p>)
+@@ -777,11 +1014,12 @@ def test_html_comments_escaped(namespace_tag, end_tag, data, expected):
+     #
+     # * img and other tags break out of the svg or math namespace (e.g. <svg><img></svg> == <svg><img></svg>)
+     # * style does not (e.g. <svg><style></svg> == <svg><style></style></svg>)
++    # * style and other tags without child elements does not (e.g. <svg><style></svg> == <svg><style></style></svg>)
+     # * the breaking tag ejects trailing elements (e.g. <svg><img><style></style></svg> == <svg></svg><img><style></style>)
+     #
+     # the ejected elements can trigger XSS
+     assert (
+-        clean(data, tags=[namespace_tag, end_tag, "style"], strip_comments=False)
++        clean(data, tags=[namespace_tag, end_tag, eject_tag], strip_comments=False)
+         == expected
+     )
+ 
+-- 
+2.31.0
+
diff -Nru python-bleach-3.2.1/debian/patches/series python-bleach-3.2.1/debian/patches/series
--- python-bleach-3.2.1/debian/patches/series	2021-01-18 07:24:44.000000000 +0100
+++ python-bleach-3.2.1/debian/patches/series	2021-04-03 16:58:05.000000000 +0200
@@ -1,3 +1,5 @@
 0001-remove-privacy-breach.patch
 0002-no_vendored_html5lib.patch
 0003-fix-py3.9-urlparse-changes.patch
+0004-sanitizer-escape-HTML-comments.patch
+0005-tests-add-tests-for-more-eject-tags-for-GHSA-vv2x-vr.patch

Reply via email to