CVE-2021-37697: Insufficient Information (NVD-CWE-noinfo)
value: tmerc-cogs are a collection of open source plugins for the Red Discord bot. A vulnerability has been found in the code that allows any user to access sensitive information by crafting a specific membership event message. Issue is patched in commit d63c49b4cfc30c795336e4fff08cba3795e0fcc0. As a workaround users may unload the Welcome cog.
CWE description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
CVSS v3 base score: 6.5
Published: 2021-08-11T23:15Z
Repository: https://github.com/tmercswims/tmerc-cogs
Language: Python
Files changed: welcome/safemodels.py, welcome/welcome.py
Commit date: 2021-08-10 20:28:01 -0700
Commit message: fix(Welcome): only allow use of safe model attributes

Diff: diff --git a/welcome/safemodels.py b/welcome/safemodels.py
new file mode 100644
index 0000000..01b310a
--- /dev/null
+++ b/welcome/safemodels.py
@@ -0,0 +1,52 @@
+import discord
+
+
+class SafeMember:
+    def __init__(self, member: discord.Member) -> None:
+        self.name = str(member.name)
+        self.display_name = str(member.display_name)
+        self.nick = str(member.nick)
+        self.id = str(member.id)
+        self.mention = str(member.mention)
+        self.discriminator = str(member.discriminator)
+        self.color = str(member.color)
+        self.colour = str(member.colour)
+        self.created_at = str(member.created_at)
+        self.joined_at = str(member.joined_at)
+
+    def __str__(self):
+        return self.name
+
+    def __getattr__(self, name):
+        return self
+
+
+class SafeRole:
+    def __init__(self, role: discord.Role) -> None:
+        self.name = str(role.name)
+        self.id = str(role.id)
+        self.mention = str(role.mention)
+        self.color = str(role.color)
+        self.colour = str(role.colour)
+        self.position = str(role.position)
+        self.created_at = str(role.created_at)
+
+    def __str__(self):
+        return self.name
+
+    def __getattr__(self, name):
+        return self
+
+
+class SafeGuild:
+    def __init__(self, guild: discord.Guild) -> None:
+        self.name = str(guild.name)
+        self.id = str(guild.id)
+        self.description = str(guild.description)
+        self.created_at = str(guild.created_at)
+
+    def __str__(self):
+        return self.name
+
+    def __getattr__(self, name):
+        return self
diff --git a/welcome/welcome.py b/welcome/welcome.py
index 0c9057a..3e487e8 100644
--- a/welcome/welcome.py
+++ b/welcome/welcome.py
@@ -8,10 +8,11 @@ from typing import Optional, Union
 from redbot.core import Config, checks, commands
 from redbot.core.utils.chat_formatting import box, humanize_list, pagify
 
 from .enums import WhisperType
 from .errors import WhisperError
+from .safemodels import SafeGuild, SafeMember
 
 __author__ = "tmerc"
 
 log = logging.getLogger("red.tmerc.welcome")
 
@@ -789,11 +790,18 @@ class Welcome(commands.Cog):
             if len(roles) > 0:
                 role_str = humanize_list(roles)
 
         try:
             return await channel.send(
-                format_str.format(member=user, server=guild, bot=user, count=count or "", plural=plural, roles=role_str)
+                format_str.format(
+                    member=SafeMember(user),
+                    server=SafeGuild(guild),
+                    bot=SafeMember(user),
+                    count=count or "",
+                    plural=plural,
+                    roles=role_str,
+                )
             )
         except discord.Forbidden:
             log.error(
                 f"Failed to send {event} message to channel ID {channel.id} (server ID {guild.id}): "
                 "insufficient permissions"

Vulnerable code:                 format_str.format(member=user, server=guild, bot=user, count=count or "", plural=plural, roles=role_str)
Fixed code: import discord


class SafeMember:
    def __init__(self, member: discord.Member) -> None:
        self.name = str(member.name)
        self.display_name = str(member.display_name)
        self.nick = str(member.nick)
        self.id = str(member.id)
        self.mention = str(member.mention)
        self.discriminator = str(member.discriminator)
        self.color = str(member.color)
        self.colour = str(member.colour)
        self.created_at = str(member.created_at)
        self.joined_at = str(member.joined_at)

    def __str__(self):
        return self.name

    def __getattr__(self, name):
        return self


class SafeRole:
    def __init__(self, role: discord.Role) -> None:
        self.name = str(role.name)
        self.id = str(role.id)
        self.mention = str(role.mention)
        self.color = str(role.color)
        self.colour = str(role.colour)
        self.position = str(role.position)
        self.created_at = str(role.created_at)

    def __str__(self):
        return self.name

    def __getattr__(self, name):
        return self


class SafeGuild:
    def __init__(self, guild: discord.Guild) -> None:
        self.name = str(guild.name)
        self.id = str(guild.id)
        self.description = str(guild.description)
        self.created_at = str(guild.created_at)

    def __str__(self):
        return self.name

    def __getattr__(self, name):
        return self
from .safemodels import SafeGuild, SafeMember
                format_str.format(
                    member=SafeMember(user),
                    server=SafeGuild(guild),
                    bot=SafeMember(user),
                    count=count or "",
                    plural=plural,
                    roles=role_str,
                )