Message context command bypasses member permission gate for guild expression creation #224
Labels
No labels
beginner friendly
bug
chore
documentation
duplicate
feature
help wanted
invalid
needs-triage
question
size/L
size/M
size/S
size/XL
size/XS
urgent
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
ScottyLabs/dalmatian#224
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Description
Category: Authorization bypass / privileged action confused deputy
CWE: CWE-862, CWE-863 (Check CWE; it is actually helpful)
Brief Summary
Steal Emotes/Stickers message context command is registered for guild use but never sets ManageGuildExpressions or performs an equivalent runtime member permission check before calling
guild.emojis.create()andguild.stickers.create(). Thus, a normal guild member can exercise bot-owned expression management authority if the bot has that permission.The root causes of this issue are as stated below (may be there are more)
src/contextCommands/steal.ts:18-22: guild context command lacks permission defaultsrc/contextCommands/steal.ts:102-106: Command performs the privileged guild expression creation side effect using bot authority.src/contextCommands/steal.ts:164-170: privileged guild state change reached from the same unguarded context commandsrc/events/interactionCreate:64-80: Dispatcher invokes context commands without local permission checkexecute()and this does not enforceManageGuildExpressionsat runtimeSuggested remediations are as stated below
.setDefaultMemberPermissions(PermissionFlagsBits.ManageuildExpressions)to the context command and also check itAlso worth adding:
The slash /steal command does set
.setDefaultMemberPermissions(PermissionFlagsBits.ManageGuildExpressions), so it is better protected at the command-registration layer than the context command. However, it still lacks a runtime permission check before using privileged guild expression APIs. Both the slash command and the context command should checkinteraction.memberPermissions?.has(PermissionFlagsBits.ManageGuildExpressions)before creating emojis, stickers, or soundboard soundsI'm pretty sure Discord handles this, so there's no way for a user to bypass the check
@TenType wrote in https://codeberg.org/ScottyLabs/dalmatian/issues/224#issuecomment-18993857:
I don't think Discord fully covers this, though. We should separate this into two parts.
The first part is that the context command has no restriction for Discord to enforce. Steal never calls setDefaultMemberPermissions(), so by default all members can use any command unless we explicitly set a restriction. So there is actually nothing gating invocation here which means, distinct from the slash command issue, this is an actual bug so aka discord can't handle this.
The second part is about where the default is set. Default member permissions only control who can invoke the command, iirc, and that is adjustable per server (a server can grant a command to additional roles via server setting overrides of the Dalmatian setting, maybe? I'm not sure about Discord server settings). Anyways, the code itself never checks that the invoking member is authorized before using the bot's own privilege. And, trivially, these are independent controls.