mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 17:31:06 +00:00
fix(discord): block channel policy auth bypass
This commit is contained in:
@@ -8,6 +8,7 @@ Docs: https://docs.openclaw.ai
|
||||
|
||||
### Fixes
|
||||
|
||||
- Discord/security: keep native slash-command channel policy from bypassing configured owner or member restrictions, while preserving channel-policy fallback when no stricter access rule exists. (#70711) Thanks @vincentkoc.
|
||||
- Android/security: stop `ASK_OPENCLAW` intents from auto-sending injected prompts, so external app actions only prefill the draft instead of dispatching it immediately. (#70714) Thanks @vincentkoc.
|
||||
- Control UI/chat: queue Stop-button aborts across Gateway reconnects so a disconnected active run is canceled on reconnect instead of only clearing local UI state. (#70673) Thanks @chinar-amrutkar.
|
||||
- Secrets/Windows: strip UTF-8 BOMs from file-backed secrets and keep unavailable ACL checks fail-closed unless trusted file or exec providers explicitly opt into `allowInsecurePath`. (#70662) Thanks @zhanggpcsu.
|
||||
|
||||
@@ -230,6 +230,67 @@ describe("Discord native slash commands with commands.allowFrom", () => {
|
||||
expectNotUnauthorizedReply(interaction);
|
||||
});
|
||||
|
||||
it("authorizes guild slash commands when channel access restrictions include the member", async () => {
|
||||
const { dispatchSpy, interaction } = await runGuildSlashCommand({
|
||||
mutateConfig: (cfg) => {
|
||||
cfg.commands = {
|
||||
...cfg.commands,
|
||||
allowFrom: undefined,
|
||||
};
|
||||
cfg.channels = {
|
||||
...cfg.channels,
|
||||
discord: {
|
||||
...cfg.channels?.discord,
|
||||
guilds: {
|
||||
"345678901234567890": {
|
||||
channels: {
|
||||
"234567890123456789": {
|
||||
enabled: true,
|
||||
requireMention: false,
|
||||
users: ["user:123456789012345678"],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
expect(dispatchSpy).toHaveBeenCalledTimes(1);
|
||||
expectNotUnauthorizedReply(interaction);
|
||||
});
|
||||
|
||||
it("rejects guild slash commands when channel access restrictions exclude the member even if channel policy would allow them", async () => {
|
||||
const { dispatchSpy, interaction } = await runGuildSlashCommand({
|
||||
userId: "999999999999999999",
|
||||
mutateConfig: (cfg) => {
|
||||
cfg.commands = {
|
||||
...cfg.commands,
|
||||
allowFrom: undefined,
|
||||
};
|
||||
cfg.channels = {
|
||||
...cfg.channels,
|
||||
discord: {
|
||||
...cfg.channels?.discord,
|
||||
guilds: {
|
||||
"345678901234567890": {
|
||||
channels: {
|
||||
"234567890123456789": {
|
||||
enabled: true,
|
||||
requireMention: false,
|
||||
users: ["user:123456789012345678"],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
expect(dispatchSpy).not.toHaveBeenCalled();
|
||||
expectUnauthorizedReply(interaction);
|
||||
});
|
||||
|
||||
it("rejects guild slash commands outside the Discord allowlist when commands.useAccessGroups is false and commands.allowFrom is not configured", async () => {
|
||||
const { dispatchSpy, interaction } = await runGuildSlashCommand({
|
||||
mutateConfig: (cfg) => {
|
||||
|
||||
@@ -543,12 +543,12 @@ describe("Discord native plugin command dispatch", () => {
|
||||
"thread-123": {
|
||||
enabled: true,
|
||||
requireMention: false,
|
||||
users: ["owner"],
|
||||
users: ["user:owner"],
|
||||
},
|
||||
"parent-456": {
|
||||
enabled: true,
|
||||
requireMention: false,
|
||||
users: ["owner"],
|
||||
users: ["user:owner"],
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -613,12 +613,12 @@ describe("Discord native plugin command dispatch", () => {
|
||||
"partial-thread-123": {
|
||||
enabled: true,
|
||||
requireMention: false,
|
||||
users: ["owner"],
|
||||
users: ["user:owner"],
|
||||
},
|
||||
"partial-parent-456": {
|
||||
enabled: true,
|
||||
requireMention: false,
|
||||
users: ["owner"],
|
||||
users: ["user:owner"],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -243,7 +243,12 @@ function resolveDiscordGuildNativeCommandAuthorized(params: {
|
||||
configured: hasAccessRestrictions,
|
||||
allowed: memberAllowed,
|
||||
};
|
||||
const fallbackAuthorizers = [policyAuthorizer, ownerAuthorizer, memberAuthorizer];
|
||||
const hasStricterAccessRestrictions = ownerAuthorizer.configured || memberAuthorizer.configured;
|
||||
const policyFallbackAuthorizer = {
|
||||
configured: policyAuthorizer.configured && !hasStricterAccessRestrictions,
|
||||
allowed: policyAuthorizer.allowed,
|
||||
};
|
||||
const fallbackAuthorizers = [policyFallbackAuthorizer, ownerAuthorizer, memberAuthorizer];
|
||||
return resolveCommandAuthorizedFromAuthorizers({
|
||||
useAccessGroups: params.useAccessGroups,
|
||||
authorizers: params.useAccessGroups
|
||||
|
||||
Reference in New Issue
Block a user