CVE-2021-21431 (published 2021-04-09T16:15Z)

sopel-channelmgnt is a channelmgnt plugin for sopel. In versions prior to 2.0.1, on some IRC servers, restrictions around the removal of the bot using the kick/kickban command could be bypassed when kicking multiple users at once. We also believe it may have been possible to remove users from other channels but due to the wonder that is IRC and following RfCs, We have no POC for that. Freenode is not affected. This is fixed in version 2.0.1. As a workaround, do not use this plugin on networks where TARGMAX > 1.

Severity: MEDIUM
CVSS v2 base score: 5.5 (AV:N/AC:L/Au:S/C:N/I:P/A:P)
CVSS v3 base score: 8.1, HIGH (CVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:C/C:N/I:H/A:H)

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/MirahezeBots/sopel-channelmgnt
commit_details: repo_url: https://github.com/MirahezeBots/sopel-channelmgnt
author: RhinosF1
author_date: 2021-04-08 18:21:42+01:00
msg: [SECURITY] Release 2.0.1 (#65)

Fixes CVE-2021-21431
repository: repo_url: https://github.com/MirahezeBots/sopel-channelmgnt
repo_name: FOSSBots/sopel-channelmgnt
description: channelmgnt plug-in for sopel
repo_language: Python
owner: MirahezeBots
file_changes: filename: dev-requirements.txt
change_type: ModificationType.MODIFY
diff: @@ -15,7 +15,7 @@ flake8-fixme==1.1.1
 flake8-multiline-containers==0.0.17
 flake8-print==4.0.0
 flake8-pytest-style==1.3.0
-flake8-return==1.1.2
+#flake8-return==1.1.2
 flake8-quotes==3.2.0
 flake8-simplify==0.13.0
 flake8-pytest==1.3

programming_language: Shell
filename: setup.py
change_type: ModificationType.MODIFY
diff: @@ -10,12 +10,12 @@ with open('requirements.txt') as requirements_file:
 
 setup(
     name='sopel_plugins.channelmgnt',
-    version='2.0',
+    version='2.0.1',
     description='Channelmgnt plugin for Sopel',
     long_description=readme,
     long_description_content_type='text/markdown',  # This is important!
     author='MirahezeBot Contributors',
-    author_email='bots@miraheze.org',
+    author_email='staff@mirahezebots.org',
     url='https://github.com/MirahezeBots/sopel-channelmgnt',
     packages=find_packages('.'),
     include_package_data=True,

programming_language: Python
filename: __init__.py
change_type: ModificationType.MODIFY
diff: @@ -216,6 +216,10 @@ def kick(bot, trigger):
             return
         nick = Identifier(text[1])
         reason = ' '.join(text[2:])
+        if ',' in str(nick):
+            return bot.reply('Unable to kick. Kicking multiple users is not allowed.')
+        if '#' in str(nick):
+            return bot.reply('Unable to kick. Use of # when kicking is not expected.')
         if nick != bot.config.core.nick and trigger.account in chanops:
             bot.write(['KICK', trigger.sender, nick, ':' + reason])
             if dodeop:
@@ -263,6 +267,10 @@ def parse_host_mask(text):
 @example('.ban Zppix')
 def ban(bot, trigger):
     """Ban a user from the channel. The bot must be a channel operator for this command to work."""
+    if ',' in str(parse_host_mask(trigger.group().split())):
+        return bot.reply('Unable to ban. Banning multiple users is not allowed.')
+    if '#' in str(parse_host_mask(trigger.group().split())):
+        return bot.reply('Unable to ban. Use of # when banning is not expected.')
     makemodechange(bot, trigger, '+b', isbqmode=True)
 
 
@@ -271,6 +279,10 @@ def ban(bot, trigger):
 @example('.unban Zppix')
 def unban(bot, trigger):
     """Unban a user from the channel. The bot must be a channel operator for this command to work."""
+    if ',' in str(parse_host_mask(trigger.group().split())):
+        return bot.reply('Unable to ban. Banning multiple users is not allowed.')
+    if '#' in str(parse_host_mask(trigger.group().split())):
+        return bot.reply('Unable to ban. Use of # when banning is not expected.')
     makemodechange(bot, trigger, '-b', isbqmode=True)
 
 
@@ -312,6 +324,10 @@ def kickban(bot, trigger):
                 deopbot(trigger.sender, bot)
             return
         nick = Identifier(text[1])
+        if ',' in str(nick):
+            return bot.reply('Unable to kickban. Kickbanning multiple users is not allowed.')
+        if '#' in str(nick):
+            return bot.reply('Unable to kickban. Use of # when kickbanning is not expected.')
         mask = text[2] if any(s in text[2] for s in '!@*') else ''
         reasonidx = 3 if mask != '' else 2
         reason = ' '.join(text[reasonidx:])

programming_language: Python