CVE-2021-41250 (published 2021-11-05T23:15Z)

Python discord bot is the community bot for the Python Discord community. In affected versions when a non-blacklisted URL and an otherwise triggering filter token is included in the same message the token filter does not trigger. This means that by including any non-blacklisted URL moderation filters can be bypassed. This issue has been resolved in commit 67390298852513d13e0213870e50fb3cff1424e0

Severity: MEDIUM
CVSS v2 base score: 4.0 (AV:N/AC:L/Au:S/C:N/I:P/A:N)
CVSS v3 base score: 4.3, MEDIUM (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N)

Weakness information:
cwe_id: NVD-CWE-Other
cwe_name: Other
description: NVD is only using a subset of CWE for mapping instead of the entire CWE, and the weakness type is not covered by that subset.
extended_description: Insufficient Information

Fix information:
repo_url: https://github.com/python-discord/bot
commit_details: repo_url: https://github.com/python-discord/bot
author: Hassan Abouelela
author_date: 2021-11-05 16:31:05+04:00
msg: Merge pull request from GHSA-j8c3-8x46-8pp6

* Don't Exit Token Filtering Early On URLs

The token filtering function would exit early if it detected a URL
within the message, but it made no extra checks to ensure there weren't
other tokens within that message that would trigger it. This made
sense when the filtering logic was written, but it's been modified since
to introduce this bug.

Regression tests included.

Signed-off-by: Hassan Abouelela <hassan@hassanamr.com>

* Links Advisory In Token Filter Tests

Adds a link to the advisory with reasoning for the existence of the
 test.

Signed-off-by: Hassan Abouelela <hassan@hassanamr.com>
repository: repo_url: https://github.com/python-discord/bot
repo_name: python-discord/bot
description: The community bot for the Python Discord community
repo_language: Python
owner: python-discord
file_changes: filename: filtering.py
change_type: ModificationType.MODIFY
diff: @@ -496,10 +496,6 @@ class Filtering(Cog):
 
         text = self.clean_input(text)
 
-        # Make sure it's not a URL
-        if URL_RE.search(text):
-            return False, None
-
         watchlist_patterns = self._get_filterlist_items('filter_token', allowed=False)
         for pattern in watchlist_patterns:
             match = re.search(pattern, text, flags=re.IGNORECASE)

programming_language: Python
filename: test_filtering.py
change_type: ModificationType.ADD
diff: @@ -0,0 +1,40 @@
+import unittest
+from unittest.mock import patch
+
+from bot.exts.filters import filtering
+from tests.helpers import MockBot, autospec
+
+
+class FilteringCogTests(unittest.IsolatedAsyncioTestCase):
+    """Tests the `Filtering` cog."""
+
+    def setUp(self):
+        """Instantiate the bot and cog."""
+        self.bot = MockBot()
+        with patch("bot.utils.scheduling.create_task", new=lambda task, **_: task.close()):
+            self.cog = filtering.Filtering(self.bot)
+
+    @autospec(filtering.Filtering, "_get_filterlist_items", pass_mocks=False, return_value=["TOKEN"])
+    async def test_token_filter(self):
+        """Ensure that a filter token is correctly detected in a message."""
+        messages = {
+            "": False,
+            "no matches": False,
+            "TOKEN": True,
+
+            # See advisory https://github.com/python-discord/bot/security/advisories/GHSA-j8c3-8x46-8pp6
+            "https://google.com TOKEN": True,
+            "https://google.com something else": False,
+        }
+
+        for message, match in messages.items():
+            with self.subTest(input=message, match=match):
+                result, _ = await self.cog._has_watch_regex_match(message)
+
+                self.assertEqual(
+                    match,
+                    bool(result),
+                    msg=f"Hit was {'expected' if match else 'not expected'} for this input."
+                )
+                if result:
+                    self.assertEqual("TOKEN", result.group())

programming_language: Python