Vulnerability: Remote Code Execution in Red Discord Bot ### Impact
A RCE exploit has been discovered in the Streams module: this exploit allows Discord users with specifically crafted "going live" messages to inject code into the Streams module's going live message. By abusing this exploit, it's possible to perform destructive actions and/or access sensitive information.

### Patches
This critical exploit has been fixed on version ``3.3.12`` & ``3.4``.

### Workarounds
Unloading the Streams module with ``unload streams`` can render this exploit not accessible. We still highly recommend updating to ``3.3.12`` or ``3.4`` to completely patch this issue.

### References
* https://github.com/Cog-Creators/Red-DiscordBot/pull/4183

### For more information
If you have any questions or comments about this advisory:
* Open an issue in [Cog-Creators/Red-DiscordBot](https://github.com/Cog-Creators/Red-DiscordBot)
* Over on our [Discord server](https://discord.gg/red)
Vulnerability ID: GHSA-7257-96vg-qf6x
CWE: CWE-94
Severity score: 8.5
Project: https://github.com/Cog-Creators/Red-DiscordBot
Published: 2020-08-21
File: redbot/cogs/streams/streams.py
Commit message: Added consume all to streams.
Commit author: Kowlin

Vulnerable version (before fix):
 async def message(self, ctx: commands.Context):      @message.command(name="mention")     @commands.guild_only()     async def with_mention(self, ctx: commands.Context, message: str = None):         """Set stream alert message when mentions are enabled.          Use `{mention}` in the message to insert the selected mentions.          Use `{stream.name}` in the message to insert the channel or user name.          For example: `[p]streamset message mention "{mention}, {stream.name} is live!"`         """         if message is not None:             guild = ctx.guild async def with_mention(self, ctx: commands.Context, message: str = None):      @message.command(name="nomention")     @commands.guild_only()     async def without_mention(self, ctx: commands.Context, message: str = None):         """Set stream alert message when mentions are disabled.          Use `{stream.name}` in the message to insert the channel or user name.          For example: `[p]streamset message nomention "{stream.name} is live!"`         """         if message is not None:             guild = ctx.guild async def check_streams(self):                                 channel.guild                             ).live_message_mention()                             if alert_msg:                                 content = alert_msg.format(mention=mention_str, stream=stream)                             else:                                 content = _("{mention}, {stream} is live!").format(                                     mention=mention_str, async def check_streams(self):                                 channel.guild                             ).live_message_nomention()                             if alert_msg:                                 content = alert_msg.format(stream=stream)                             else:                                 content = _("{stream} is live!").format(                                     stream=escape(

Fixed version (after fix):
 async def message(self, ctx: commands.Context):      @message.command(name="mention")     @commands.guild_only()     async def with_mention(self, ctx: commands.Context, *, message: str = None):         """Set stream alert message when mentions are enabled.          Use `{mention}` in the message to insert the selected mentions.         Use `{stream}` in the message to insert the channel or user name.          For example: `[p]streamset message mention "{mention}, {stream} is live!"`         """         if message is not None:             guild = ctx.guild async def with_mention(self, ctx: commands.Context, message: str = None):      @message.command(name="nomention")     @commands.guild_only()     async def without_mention(self, ctx: commands.Context, *, message: str = None):         """Set stream alert message when mentions are disabled.          Use `{stream}` in the message to insert the channel or user name.          For example: `[p]streamset message nomention "{stream} is live!"`         """         if message is not None:             guild = ctx.guild async def check_streams(self):                                 channel.guild                             ).live_message_mention()                             if alert_msg:                                 content = alert_msg  # Stop bad things from happening here...                                 content = content.replace("{stream.name}", str(stream.name))  # Backwards compatability                                 content = content.replace("{stream}", str(stream.name))                                 content = content.replace("{mention}", mention_str)                             else:                                 content = _("{mention}, {stream} is live!").format(                                     mention=mention_str, async def check_streams(self):                                 channel.guild                             ).live_message_nomention()                             if alert_msg:                                 content = alert_msg  # Stop bad things from happening here...                                 content = content.replace("{stream.name}", str(stream.name))  # Backwards compatability                                 content = content.replace("{stream}", str(stream.name))                             else:                                 content = _("{stream} is live!").format(                                     stream=escape(

Patch:
patch: @@ -497,14 +497,13 @@ async def message(self, ctx: commands.Context):
 
     @message.command(name="mention")
     @commands.guild_only()
-    async def with_mention(self, ctx: commands.Context, message: str = None):
+    async def with_mention(self, ctx: commands.Context, *, message: str = None):
         """Set stream alert message when mentions are enabled.
 
         Use `{mention}` in the message to insert the selected mentions.
+        Use `{stream}` in the message to insert the channel or user name.
 
-        Use `{stream.name}` in the message to insert the channel or user name.
-
-        For example: `[p]streamset message mention "{mention}, {stream.name} is live!"`
+        For example: `[p]streamset message mention "{mention}, {stream} is live!"`
         """
         if message is not None:
             guild = ctx.guild
@@ -515,12 +514,12 @@ async def with_mention(self, ctx: commands.Context, message: str = None):
 
     @message.command(name="nomention")
     @commands.guild_only()
-    async def without_mention(self, ctx: commands.Context, message: str = None):
+    async def without_mention(self, ctx: commands.Context, *, message: str = None):
         """Set stream alert message when mentions are disabled.
 
-        Use `{stream.name}` in the message to insert the channel or user name.
+        Use `{stream}` in the message to insert the channel or user name.
 
-        For example: `[p]streamset message nomention "{stream.name} is live!"`
+        For example: `[p]streamset message nomention "{stream} is live!"`
         """
         if message is not None:
             guild = ctx.guild
@@ -720,7 +719,10 @@ async def check_streams(self):
                                 channel.guild
                             ).live_message_mention()
                             if alert_msg:
-                                content = alert_msg.format(mention=mention_str, stream=stream)
+                                content = alert_msg  # Stop bad things from happening here...
+                                content = content.replace("{stream.name}", str(stream.name))  # Backwards compatability
+                                content = content.replace("{stream}", str(stream.name))
+                                content = content.replace("{mention}", mention_str)
                             else:
                                 content = _("{mention}, {stream} is live!").format(
                                     mention=mention_str,
@@ -733,7 +735,9 @@ async def check_streams(self):
                                 channel.guild
                             ).live_message_nomention()
                             if alert_msg:
-                                content = alert_msg.format(stream=stream)
+                                content = alert_msg  # Stop bad things from happening here...
+                                content = content.replace("{stream.name}", str(stream.name))  # Backwards compatability
+                                content = content.replace("{stream}", str(stream.name))
                             else:
                                 content = _("{stream} is live!").format(
                                     stream=escape(
path: redbot/cogs/streams/streams.py