mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 07:10:43 +00:00
fix(discord): move in-check inside try/catch in channel-access helper
Wrap the `key in channel` probe inside the existing `try/catch` in `readDiscordChannelPropertySafe` so a throwing Proxy `has` trap (or any other reflective error on the presence check) degrades to `undefined` instead of propagating, matching the existing behavior for throwing getters on the value read. Add a regression test that exposes the interaction channel through a Proxy whose `has` trap throws on `parentId` and asserts the slash-command path still defers and dispatches. No behavior change for Carbon prototype getters or plain-object channels: the safe accessor still traverses the prototype chain (required for Carbon's `GuildThreadChannel.parentId`), still returns `undefined` for missing or throwing reads, and still preserves null-to-undefined coercion downstream.
This commit is contained in:
committed by
Peter Steinberger
parent
dbf8fd0db7
commit
349d86c152
@@ -1,8 +1,11 @@
|
||||
function readDiscordChannelPropertySafe(channel: unknown, key: string): unknown {
|
||||
if (!channel || typeof channel !== "object" || !(key in channel)) {
|
||||
if (!channel || typeof channel !== "object") {
|
||||
return undefined;
|
||||
}
|
||||
try {
|
||||
if (!(key in channel)) {
|
||||
return undefined;
|
||||
}
|
||||
return (channel as Record<string, unknown>)[key];
|
||||
} catch {
|
||||
return undefined;
|
||||
|
||||
@@ -215,6 +215,31 @@ describe("Discord native slash commands with commands.allowFrom", () => {
|
||||
expectNotUnauthorizedReply(interaction);
|
||||
});
|
||||
|
||||
it("tolerates guild thread channels exposed through a Proxy whose has trap throws", async () => {
|
||||
const { dispatchSpy, interaction } = await runGuildSlashCommand({
|
||||
mutateInteraction: (currentInteraction) => {
|
||||
const baseChannel = {
|
||||
type: ChannelType.PublicThread,
|
||||
id: currentInteraction.channel.id,
|
||||
};
|
||||
currentInteraction.channel = new Proxy(baseChannel, {
|
||||
has(target, key) {
|
||||
if (key === "parentId") {
|
||||
throw new Error("has-trap denied");
|
||||
}
|
||||
return key in target;
|
||||
},
|
||||
get(target, key, receiver) {
|
||||
return Reflect.get(target, key, receiver);
|
||||
},
|
||||
}) as MockCommandInteraction["channel"];
|
||||
},
|
||||
});
|
||||
expect(interaction.defer).toHaveBeenCalledTimes(1);
|
||||
expect(dispatchSpy).toHaveBeenCalledTimes(1);
|
||||
expectNotUnauthorizedReply(interaction);
|
||||
});
|
||||
|
||||
it("authorizes guild slash commands from an allowlisted channel when commands.allowFrom is not configured", async () => {
|
||||
const { dispatchSpy, interaction } = await runGuildSlashCommand({
|
||||
mutateConfig: (cfg) => {
|
||||
|
||||
Reference in New Issue
Block a user