Repository: fedora-infra/bodhi

Issue:
CVE-2017-1002152: JavaScript injection via Bugzilla ticket subjects
[Marcel reported](https://bugzilla.redhat.com/show_bug.cgi?id=1478587) that it is possible to inject JavaScript into Bodhi's web interface through Bugzilla ticket subjects. The reporter cited [an update](https://bodhi.fedoraproject.org/updates/FEDORA-2017-3c92db10b8) that did not properly escape tags from the bug it was associated with.

We should run the bugzilla text through bleach, similar to what we do for comments from our users.


Discussion:

Resolving patch:
diff --git a/bodhi/server/util.py b/bodhi/server/util.py
--- a/bodhi/server/util.py
+++ b/bodhi/server/util.py
@@ -573,8 +573,9 @@ def bug_link(context, bug, short=False):
     link = "<a target='_blank' href='%s'>%s</a>" % (url, display)
     if not short:
         if bug.title:
-            # We're good...
-            link = link + " " + bug.title
+            # We're good, but we do need to clean the bug title in case it contains malicious
+            # tags. See CVE-2017-1002152: https://github.com/fedora-infra/bodhi/issues/1740
+            link = link + " " + bleach.clean(bug.title, tags=[], attributes=[])
         else:
             # Otherwise, the backend is async grabbing the title from rhbz, so
             link = link + " <img class='spinner' src='static/img/spinner.gif'>"


Test patch:
diff --git a/bodhi/tests/server/test_utils.py b/bodhi/tests/server/test_util.py
similarity index 92%
rename from bodhi/tests/server/test_utils.py
rename to bodhi/tests/server/test_util.py
--- a/bodhi/tests/server/test_utils.py
+++ b/bodhi/tests/server/test_util.py
@@ -1,3 +1,8 @@
+# -*- coding: utf-8 -*-
+# Copyright © 2007-2017 Red Hat, Inc. and others.
+#
+# This file is part of Bodhi.
+#
 # This program is free software; you can redistribute it and/or
 # modify it under the terms of the GNU General Public License
 # as published by the Free Software Foundation; either version 2
@@ -23,6 +28,80 @@
 from bodhi.server.models import TestGatingStatus
 
 
+class TestBugLink(unittest.TestCase):
+    """Tests for the bug_link() function."""
+    def test_short_false_with_title(self):
+        """Test a call to bug_link() with short=False on a Bug that has a title."""
+        bug = mock.MagicMock()
+        bug.bug_id = 1234567
+        bug.title = "Lucky bug number"
+
+        link = util.bug_link(None, bug)
+
+        self.assertEqual(
+            link,
+            ("<a target='_blank' href='https://bugzilla.redhat.com/show_bug.cgi?id=1234567'>"
+             "#1234567</a> Lucky bug number"))
+
+    def test_short_false_with_title_sanitizes_safe_tags(self):
+        """
+        Test that a call to bug_link() with short=False on a Bug that has a title sanitizes even
+        safe tags because really they should be rendered human readable.
+        """
+        bug = mock.MagicMock()
+        bug.bug_id = 1234567
+        bug.title = 'Check <b>this</b> out'
+
+        link = util.bug_link(None, bug)
+
+        self.assertEqual(
+            link,
+            ("<a target='_blank' href='https://bugzilla.redhat.com/show_bug.cgi?id=1234567'>"
+             "#1234567</a> Check &lt;b&gt;this&lt;/b&gt; out"))
+
+    def test_short_false_with_title_sanitizes_unsafe_tags(self):
+        """
+        Test that a call to bug_link() with short=False on a Bug that has a title sanitizes unsafe
+        tags.
+        """
+        bug = mock.MagicMock()
+        bug.bug_id = 1473091
+        bug.title = '<disk> <driver name="..."> should be optional'
+
+        link = util.bug_link(None, bug)
+
+        self.assertEqual(
+            link,
+            ("<a target='_blank' href='https://bugzilla.redhat.com/show_bug.cgi?id=1473091'>"
+             "#1473091</a> &lt;disk&gt; &lt;driver name=\"...\"&gt; should be optional"))
+
+    def test_short_false_without_title(self):
+        """Test a call to bug_link() with short=False on a Bug that has no title."""
+        bug = mock.MagicMock()
+        bug.bug_id = 1234567
+        bug.title = None
+
+        link = util.bug_link(None, bug)
+
+        self.assertEqual(
+            link,
+            ("<a target='_blank' href='https://bugzilla.redhat.com/show_bug.cgi?id=1234567'>"
+             "#1234567</a> <img class='spinner' src='static/img/spinner.gif'>"))
+
+    def test_short_true(self):
+        """Test a call to bug_link() with short=True."""
+        bug = mock.MagicMock()
+        bug.bug_id = 1234567
+        bug.title = "Lucky bug number"
+
+        link = util.bug_link(None, bug, True)
+
+        self.assertEqual(
+            link,
+            ("<a target='_blank' href='https://bugzilla.redhat.com/show_bug.cgi?id=1234567'>"
+             "#1234567</a>"))
+
+
 class TestUtils(unittest.TestCase):
 
     def setUp(self):