Skip to content

fix(discord): honor commands.allowFrom in guild slash auth#38794

Merged
thewilloftheshadow merged 6 commits into
openclaw:mainfrom
jskoiz:codex/discord-native-commands-allowfrom
Mar 7, 2026
Merged

fix(discord): honor commands.allowFrom in guild slash auth#38794
thewilloftheshadow merged 6 commits into
openclaw:mainfrom
jskoiz:codex/discord-native-commands-allowfrom

Conversation

@jskoiz
Copy link
Copy Markdown
Contributor

@jskoiz jskoiz commented Mar 7, 2026

Summary

  • honor commands.allowFrom.discord for native Discord slash commands in guild channels
  • reuse the shared command authorization logic so guild slash auth matches the text-command path
  • add a regression test covering an allowlisted sender in an allowlisted guild channel

Root cause

Discord native slash commands in guild channels only considered Discord owner/channel member allowlists during the pre-dispatch auth check. If commands.allowFrom.discord was configured without matching channels.discord.allowFrom or guild users/roles, /new and other native commands returned You are not authorized to use this command. even though the shared command auth layer would allow that sender.

Fix

  • resolve command authorization for Discord native slash commands before the guild command gate
  • treat an explicit commands.allowFrom.discord match as a valid guild slash-command authorizer
  • keep guild/channel allowlisting intact so this does not bypass channel visibility policy

Test plan

  • pnpm test src/discord/monitor/native-command.commands-allowfrom.test.ts
  • pnpm build
  • pnpm check currently fails on upstream main with an unrelated TypeScript error in extensions/feishu/src/monitor.test-mocks.ts

Fixes #19310

AI disclosure: This PR is AI-assisted. It has been tested locally with the commands above, and I understand what the code does.

Copilot AI review requested due to automatic review settings March 7, 2026 11:15
@openclaw-barnacle openclaw-barnacle Bot added channel: discord Channel integration: discord size: S labels Mar 7, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates Discord guild slash-command authorization to honor commands.allowFrom.discord (and commands.allowFrom["*"]) by reusing the shared command authorization resolver, plus a regression test ensuring an allowlisted sender can run native commands in an allowlisted guild channel.

Changes:

  • Add resolveDiscordNativeCommandAllowlistAccess() and integrate it into guild slash-command gating as an additional authorizer.
  • Ensure guild slash-command auth uses the shared resolveCommandAuthorization() behavior for commands.allowFrom.
  • Add a regression test for commands.allowFrom.discord in a guild channel.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
src/discord/monitor/native-command.ts Adds a commands.allowFrom-backed authorizer to the guild slash-command authorization path via shared command-auth logic.
src/discord/monitor/native-command.commands-allowfrom.test.ts Adds a vitest regression test covering an allowlisted Discord user invoking a native slash command in a guild channel.

Comment thread src/discord/monitor/native-command.commands-allowfrom.test.ts Outdated
Comment thread src/discord/monitor/native-command.ts Outdated
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Mar 7, 2026

Greptile Summary

This PR fixes a genuine authorization gap where commands.allowFrom.discord was not consulted when deciding whether to allow guild slash commands. Before the fix, only Discord owner/channel-member allowlists were checked, so senders allowed by commands.allowFrom alone received a spurious "You are not authorized" response.

The fix introduces resolveDiscordNativeCommandAllowlistAccess, which reuses the shared resolveCommandAuthorization path and wires the result as an additional authorizer ahead of the existing owner and member checks. The logic is sound: the Discord channel dock's formatAllowFrom function strips the user: prefix during both allow-list and sender-candidate normalization, so "user:123456789012345678" in config correctly matches the raw sender ID at runtime.

Key observations:

  • The new authorizer is prepended in both the useAccessGroups and non-useAccessGroups branches, which is consistent with how the other authorizers are used.
  • The change also takes effect for group DMs (not just guild text channels), since both share the !isDirectMessage code path. This is likely desirable but is not mentioned in the PR description.

Confidence Score: 4/5

  • Safe to merge. The core fix is logically correct and preserves all existing authorization paths without introducing regressions.
  • This PR correctly fixes the authorization gap by reusing the shared command auth logic. The implementation is sound and integration is clean. The deduction from a perfect score is for incomplete test coverage: a negative test case would improve regression detection and make the test suite more robust.
  • src/discord/monitor/native-command.commands-allowfrom.test.ts - consider adding a negative test case to verify that non-allowlisted senders are still denied.

Last reviewed commit: aaba93e

Comment on lines +76 to +122
},
},
},
},
},
},
} as OpenClawConfig;
}

describe("Discord native slash commands with commands.allowFrom", () => {
it("authorizes guild slash commands when commands.allowFrom.discord matches the sender", async () => {
const cfg = createConfig();
const commandSpec: NativeCommandSpec = {
name: "status",
description: "Status",
acceptsArgs: false,
};
const command = createDiscordNativeCommand({
command: commandSpec,
cfg,
discordConfig: cfg.channels?.discord ?? {},
accountId: "default",
sessionPrefix: "discord:slash",
ephemeralDefault: true,
threadBindings: createNoopThreadBindingManager("default"),
});
const interaction = createInteraction();

vi.spyOn(pluginCommandsModule, "matchPluginCommand").mockReturnValue(null);
const dispatchSpy = vi
.spyOn(dispatcherModule, "dispatchReplyWithDispatcher")
.mockResolvedValue({
counts: {
final: 1,
block: 0,
tool: 0,
},
} as never);

await (command as { run: (interaction: unknown) => Promise<void> }).run(interaction as unknown);

expect(dispatchSpy).toHaveBeenCalledTimes(1);
expect(interaction.reply).not.toHaveBeenCalledWith(
expect.objectContaining({ content: "You are not authorized to use this command." }),
);
});
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing negative test case for rejection

The test only verifies the happy path: that an allowlisted sender is authorized. There is no assertion that a sender who is not in commands.allowFrom.discord still receives "You are not authorized to use this command." in the guild slash command path.

Without this, the test suite can't catch a regression that accidentally grants access to everyone (e.g., if the configured/allowed logic in resolveCommandAuthorizedFromAuthorizers breaks). Consider adding a second it block that creates a sender with a different userId (not in the allowlist), confirms dispatchSpy is not called, and confirms interaction.reply is called with the authorization-denied message.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/discord/monitor/native-command.commands-allowfrom.test.ts
Line: 76-122

Comment:
Missing negative test case for rejection

The test only verifies the happy path: that an allowlisted sender is authorized. There is no assertion that a sender who is *not* in `commands.allowFrom.discord` still receives `"You are not authorized to use this command."` in the guild slash command path.

Without this, the test suite can't catch a regression that accidentally grants access to everyone (e.g., if the `configured`/`allowed` logic in `resolveCommandAuthorizedFromAuthorizers` breaks). Consider adding a second `it` block that creates a sender with a different `userId` (not in the allowlist), confirms `dispatchSpy` is *not* called, and confirms `interaction.reply` is called with the authorization-denied message.

How can I resolve this? If you propose a fix, please make it concise.

@jskoiz
Copy link
Copy Markdown
Contributor Author

jskoiz commented Mar 7, 2026

Addressed the review feedback in ab20472.

Changes:

  • switched the test to import ChannelType from @buape/carbon to match the implementation surface
  • aligned the guild slash auth helper to use ChatType: "channel" for guild channels while preserving group for group DMs
  • added a negative regression test to verify non-allowlisted senders still get "You are not authorized to use this command."

Retested:

  • pnpm test src/discord/monitor/native-command.commands-allowfrom.test.ts

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

@jskoiz
Copy link
Copy Markdown
Contributor Author

jskoiz commented Mar 7, 2026

@thewilloftheshadow tagging you because Discord appears to be your domain based on the maintainer/contributing notes, and this fix is specifically in the native Discord slash-command auth path.

If someone else is a better reviewer for this auth behavior, happy to retarget.

@thewilloftheshadow thewilloftheshadow self-assigned this Mar 7, 2026
@thewilloftheshadow thewilloftheshadow force-pushed the codex/discord-native-commands-allowfrom branch from 25d1599 to 2b2f8bd Compare March 7, 2026 18:03
@thewilloftheshadow thewilloftheshadow merged commit 262fef6 into openclaw:main Mar 7, 2026
5 checks passed
@thewilloftheshadow
Copy link
Copy Markdown
Member

Landed via temp rebase onto main.

  • Gate: pnpm test src/discord/monitor/native-command.commands-allowfrom.test.ts
  • Land commit: 2b2f8bd
  • Merge commit: 262fef6

Thanks @jskoiz!

vincentkoc added a commit that referenced this pull request Mar 7, 2026
* origin/main: (40 commits)
  fix(discord): honor commands.allowFrom in guild slash auth (#38794)
  test: narrow pairing setup helper token type
  refactor(agents): share skill plugin fixture writer in tests
  refactor(auto-reply): share discord auth registry test fixture
  refactor(test-utils): share direct channel plugin test fixture
  refactor(commands): dedupe config-only channel status fixtures
  refactor(commands): dedupe channel plugin test fixture builders
  refactor(tui): dedupe mode-specific exec secret fixtures
  refactor(tui): dedupe gateway token resolution path
  refactor(memory): dedupe local embedding init concurrency fixtures
  refactor(feishu): dedupe non-streaming reply dispatcher setup
  refactor(feishu): dedupe accounts env secret-ref checks
  refactor(feishu): dedupe client timeout assertion scaffolding
  refactor(feishu): dedupe onboarding status env setup tests
  refactor(web): dedupe self-chat response-prefix tests
  refactor(pairing): dedupe inferred auth token fixtures
  refactor(gateway): dedupe blocked chat reply mock setup
  refactor(gateway): dedupe maintenance timer test setup
  refactor(gateway): dedupe legacy migration validation assertions
  refactor(gateway): dedupe probe route assertion loops
  ...

# Conflicts:
#	extensions/feishu/src/onboarding.test.ts
#	extensions/googlechat/src/channel.outbound.test.ts
#	src/agents/minimax-vlm.normalizes-api-key.test.ts
#	src/pairing/setup-code.test.ts
mcaxtr pushed a commit to mcaxtr/openclaw that referenced this pull request Mar 7, 2026
…38794)

* fix(discord): honor commands.allowFrom in guild slash auth

* Update native-command.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update native-command.commands-allowfrom.test.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix(discord): address slash auth review feedback

* test(discord): add slash auth coverage for allowFrom variants

* fix: add changelog entry for discord slash auth fix (openclaw#38794) (thanks @jskoiz)

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Shadow <hi@shadowing.dev>
vincentkoc pushed a commit to BryanTegomoh/openclaw-upstream that referenced this pull request Mar 8, 2026
…38794)

* fix(discord): honor commands.allowFrom in guild slash auth

* Update native-command.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update native-command.commands-allowfrom.test.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix(discord): address slash auth review feedback

* test(discord): add slash auth coverage for allowFrom variants

* fix: add changelog entry for discord slash auth fix (openclaw#38794) (thanks @jskoiz)

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Shadow <hi@shadowing.dev>
openperf pushed a commit to openperf/moltbot that referenced this pull request Mar 8, 2026
…38794)

* fix(discord): honor commands.allowFrom in guild slash auth

* Update native-command.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update native-command.commands-allowfrom.test.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix(discord): address slash auth review feedback

* test(discord): add slash auth coverage for allowFrom variants

* fix: add changelog entry for discord slash auth fix (openclaw#38794) (thanks @jskoiz)

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Shadow <hi@shadowing.dev>
GordonSH-oss pushed a commit to GordonSH-oss/openclaw that referenced this pull request Mar 9, 2026
…38794)

* fix(discord): honor commands.allowFrom in guild slash auth

* Update native-command.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update native-command.commands-allowfrom.test.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix(discord): address slash auth review feedback

* test(discord): add slash auth coverage for allowFrom variants

* fix: add changelog entry for discord slash auth fix (openclaw#38794) (thanks @jskoiz)

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Shadow <hi@shadowing.dev>
jenawant pushed a commit to jenawant/openclaw that referenced this pull request Mar 10, 2026
…38794)

* fix(discord): honor commands.allowFrom in guild slash auth

* Update native-command.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update native-command.commands-allowfrom.test.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix(discord): address slash auth review feedback

* test(discord): add slash auth coverage for allowFrom variants

* fix: add changelog entry for discord slash auth fix (openclaw#38794) (thanks @jskoiz)

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Shadow <hi@shadowing.dev>
V-Gutierrez pushed a commit to V-Gutierrez/openclaw-vendor that referenced this pull request Mar 17, 2026
…38794)

* fix(discord): honor commands.allowFrom in guild slash auth

* Update native-command.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update native-command.commands-allowfrom.test.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix(discord): address slash auth review feedback

* test(discord): add slash auth coverage for allowFrom variants

* fix: add changelog entry for discord slash auth fix (openclaw#38794) (thanks @jskoiz)

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Shadow <hi@shadowing.dev>
alexey-pelykh pushed a commit to remoteclaw/remoteclaw that referenced this pull request Mar 20, 2026
…38794)

* fix(discord): honor commands.allowFrom in guild slash auth

* Update native-command.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update native-command.commands-allowfrom.test.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix(discord): address slash auth review feedback

* test(discord): add slash auth coverage for allowFrom variants

* fix: add changelog entry for discord slash auth fix (openclaw#38794) (thanks @jskoiz)

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Shadow <hi@shadowing.dev>
(cherry picked from commit 262fef6)
alexey-pelykh pushed a commit to remoteclaw/remoteclaw that referenced this pull request Mar 20, 2026
…38794)

* fix(discord): honor commands.allowFrom in guild slash auth

* Update native-command.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update native-command.commands-allowfrom.test.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix(discord): address slash auth review feedback

* test(discord): add slash auth coverage for allowFrom variants

* fix: add changelog entry for discord slash auth fix (openclaw#38794) (thanks @jskoiz)

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Shadow <hi@shadowing.dev>
(cherry picked from commit 262fef6)
lovewanwan pushed a commit to lovewanwan/openclaw that referenced this pull request Apr 28, 2026
…38794)

* fix(discord): honor commands.allowFrom in guild slash auth

* Update native-command.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update native-command.commands-allowfrom.test.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix(discord): address slash auth review feedback

* test(discord): add slash auth coverage for allowFrom variants

* fix: add changelog entry for discord slash auth fix (openclaw#38794) (thanks @jskoiz)

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Shadow <hi@shadowing.dev>
ogt-redknie pushed a commit to ogt-redknie/OPENX that referenced this pull request May 2, 2026
…38794)

* fix(discord): honor commands.allowFrom in guild slash auth

* Update native-command.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update native-command.commands-allowfrom.test.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix(discord): address slash auth review feedback

* test(discord): add slash auth coverage for allowFrom variants

* fix: add changelog entry for discord slash auth fix (openclaw#38794) (thanks @jskoiz)

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Shadow <hi@shadowing.dev>
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
…38794)

* fix(discord): honor commands.allowFrom in guild slash auth

* Update native-command.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update native-command.commands-allowfrom.test.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix(discord): address slash auth review feedback

* test(discord): add slash auth coverage for allowFrom variants

* fix: add changelog entry for discord slash auth fix (openclaw#38794) (thanks @jskoiz)

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Shadow <hi@shadowing.dev>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: discord Channel integration: discord size: M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Discord Slash Commands Require Owner Configuration in Channels Despite Pairing

3 participants