






















@@ -136,6 +136,69 @@ describe("registerSlackReactionEvents", () => {
136136},
137137expectedCalls: 0,
138138},
139+{
140+name: "blocks reactions when reaction notifications are off",
141+input: { overrides: { dmPolicy: "open", reactionMode: "off" } },
142+expectedCalls: 0,
143+},
144+{
145+name: "blocks own-mode reactions on messages not authored by the bot",
146+input: {
147+overrides: { dmPolicy: "open", reactionMode: "own" },
148+event: {
149+ ...buildReactionEvent(),
150+item_user: "U_OTHER",
151+},
152+},
153+expectedCalls: 0,
154+},
155+{
156+name: "allows own-mode reactions on messages authored by the bot",
157+input: {
158+overrides: { dmPolicy: "open", reactionMode: "own" },
159+event: {
160+ ...buildReactionEvent(),
161+item_user: "U_BOT",
162+},
163+},
164+expectedCalls: 1,
165+},
166+{
167+name: "blocks reactions from senders outside the reaction allowlist",
168+input: {
169+overrides: {
170+dmPolicy: "open",
171+reactionMode: "allowlist",
172+reactionAllowlist: ["U2"],
173+},
174+event: buildReactionEvent({ user: "U1" }),
175+},
176+expectedCalls: 0,
177+},
178+{
179+name: "blocks allowlist-mode reactions when the reaction allowlist is empty",
180+input: {
181+overrides: {
182+dmPolicy: "open",
183+reactionMode: "allowlist",
184+reactionAllowlist: [],
185+},
186+event: buildReactionEvent({ user: "U1" }),
187+},
188+expectedCalls: 0,
189+},
190+{
191+name: "allows reactions from senders inside the reaction allowlist",
192+input: {
193+overrides: {
194+dmPolicy: "open",
195+reactionMode: "allowlist",
196+reactionAllowlist: ["U1"],
197+},
198+event: buildReactionEvent({ user: "U1" }),
199+},
200+expectedCalls: 1,
201+},
139202];
140203141204it.each(cases)("$name", async ({ input, expectedCalls }) => {
@@ -161,6 +224,65 @@ describe("registerSlackReactionEvents", () => {
161224expect(trackEvent).toHaveBeenCalledTimes(1);
162225});
163226227+it("marks queued reaction events as untrusted external content", async () => {
228+await executeReactionCase();
229+230+expect(reactionQueueMock).toHaveBeenCalledWith(expect.any(String), {
231+sessionKey: "agent:main:main",
232+contextKey: "slack:reaction:added:D1:123.456:U1:thumbsup",
233+trusted: false,
234+});
235+});
236+237+it("drops off-mode reactions before resolving Slack context", async () => {
238+reactionQueueMock.mockClear();
239+const harness = createSlackSystemEventTestHarness({ reactionMode: "off" });
240+const resolveChannelName = vi.fn(harness.ctx.resolveChannelName);
241+const resolveUserName = vi.fn(harness.ctx.resolveUserName);
242+harness.ctx.resolveChannelName = resolveChannelName;
243+harness.ctx.resolveUserName = resolveUserName;
244+registerSlackReactionEvents({ ctx: harness.ctx });
245+const handler = requireReactionHandler(
246+harness.getHandler("reaction_added") as ReactionHandler | null,
247+"added",
248+);
249+250+await handler({
251+event: buildReactionEvent({ user: "U777", channel: "D123" }),
252+body: {},
253+});
254+255+expect(resolveChannelName).not.toHaveBeenCalled();
256+expect(resolveUserName).not.toHaveBeenCalled();
257+expect(reactionQueueMock).not.toHaveBeenCalled();
258+});
259+260+it("drops own-mode reactions on non-bot messages before resolving Slack context", async () => {
261+reactionQueueMock.mockClear();
262+const harness = createSlackSystemEventTestHarness({ reactionMode: "own" });
263+const resolveChannelName = vi.fn(harness.ctx.resolveChannelName);
264+const resolveUserName = vi.fn(harness.ctx.resolveUserName);
265+harness.ctx.resolveChannelName = resolveChannelName;
266+harness.ctx.resolveUserName = resolveUserName;
267+registerSlackReactionEvents({ ctx: harness.ctx });
268+const handler = requireReactionHandler(
269+harness.getHandler("reaction_added") as ReactionHandler | null,
270+"added",
271+);
272+273+await handler({
274+event: {
275+ ...buildReactionEvent({ user: "U777", channel: "D123" }),
276+item_user: "U_OTHER",
277+},
278+body: {},
279+});
280+281+expect(resolveChannelName).not.toHaveBeenCalled();
282+expect(resolveUserName).not.toHaveBeenCalled();
283+expect(reactionQueueMock).not.toHaveBeenCalled();
284+});
285+164286it("passes sender context when resolving reaction session keys", async () => {
165287reactionQueueMock.mockClear();
166288const harness = createSlackSystemEventTestHarness();
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。