Files
openclaw/src/channels/plugins/message-actions.security.test.ts
2026-03-15 22:53:03 -07:00

83 lines
2.6 KiB
TypeScript

import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { jsonResult } from "../../agents/tools/common.js";
import type { OpenClawConfig } from "../../config/config.js";
import { setActivePluginRegistry } from "../../plugins/runtime.js";
import {
createChannelTestPluginBase,
createTestRegistry,
} from "../../test-utils/channel-plugins.js";
import { dispatchChannelMessageAction } from "./message-actions.js";
import type { ChannelPlugin } from "./types.js";
const handleAction = vi.fn(async () => jsonResult({ ok: true }));
const emptyRegistry = createTestRegistry([]);
const discordPlugin: ChannelPlugin = {
...createChannelTestPluginBase({
id: "discord",
label: "Discord",
capabilities: { chatTypes: ["direct", "group"] },
config: {
listAccountIds: () => ["default"],
},
}),
actions: {
listActions: () => ["kick"],
supportsAction: ({ action }) => action === "kick",
requiresTrustedRequesterSender: ({ action, toolContext }) =>
Boolean(action === "kick" && toolContext),
handleAction,
},
};
describe("dispatchChannelMessageAction trusted sender guard", () => {
beforeEach(() => {
handleAction.mockClear();
setActivePluginRegistry(
createTestRegistry([{ pluginId: "discord", source: "test", plugin: discordPlugin }]),
);
});
afterEach(() => {
setActivePluginRegistry(emptyRegistry);
});
it("rejects privileged discord moderation action without trusted sender in tool context", async () => {
await expect(
dispatchChannelMessageAction({
channel: "discord",
action: "kick",
cfg: {} as OpenClawConfig,
params: { guildId: "g1", userId: "u1" },
toolContext: { currentChannelProvider: "discord" },
}),
).rejects.toThrow("Trusted sender identity is required for discord:kick");
expect(handleAction).not.toHaveBeenCalled();
});
it("allows privileged discord moderation action with trusted sender in tool context", async () => {
await dispatchChannelMessageAction({
channel: "discord",
action: "kick",
cfg: {} as OpenClawConfig,
params: { guildId: "g1", userId: "u1" },
requesterSenderId: "trusted-user",
toolContext: { currentChannelProvider: "discord" },
});
expect(handleAction).toHaveBeenCalledOnce();
});
it("does not require trusted sender without tool context", async () => {
await dispatchChannelMessageAction({
channel: "discord",
action: "kick",
cfg: {} as OpenClawConfig,
params: { guildId: "g1", userId: "u1" },
});
expect(handleAction).toHaveBeenCalledOnce();
});
});