diff --git a/src/telegram/bot.create-telegram-bot.test.ts b/src/telegram/bot.create-telegram-bot.test.ts index ad304efdeab..942a1c6c2b3 100644 --- a/src/telegram/bot.create-telegram-bot.test.ts +++ b/src/telegram/bot.create-telegram-bot.test.ts @@ -813,6 +813,29 @@ describe("createTelegramBot", () => { }, expectedReplyCount: 1, }, + { + name: "blocks group messages when per-group allowFrom override is explicitly empty", + config: { + channels: { + telegram: { + groupPolicy: "open", + groups: { + "-100123456789": { + allowFrom: [], + requireMention: false, + }, + }, + }, + }, + }, + message: { + chat: { id: -100123456789, type: "group", title: "Test Group" }, + from: { id: 999999, username: "random" }, + text: "hello", + date: 1736380800, + }, + expectedReplyCount: 0, + }, { name: "allows all group messages when groupPolicy is 'open'", config: { diff --git a/src/telegram/group-access.base-access.test.ts b/src/telegram/group-access.base-access.test.ts new file mode 100644 index 00000000000..d8d559feab4 --- /dev/null +++ b/src/telegram/group-access.base-access.test.ts @@ -0,0 +1,56 @@ +import { describe, expect, it } from "vitest"; +import type { NormalizedAllowFrom } from "./bot-access.js"; +import { evaluateTelegramGroupBaseAccess } from "./group-access.js"; + +function allow(entries: string[], hasWildcard = false): NormalizedAllowFrom { + return { + entries, + hasWildcard, + hasEntries: entries.length > 0 || hasWildcard, + invalidEntries: [], + }; +} + +describe("evaluateTelegramGroupBaseAccess", () => { + it("fails closed when explicit group allowFrom override is empty", () => { + const result = evaluateTelegramGroupBaseAccess({ + isGroup: true, + hasGroupAllowOverride: true, + effectiveGroupAllow: allow([]), + senderId: "12345", + senderUsername: "tester", + enforceAllowOverride: true, + requireSenderForAllowOverride: true, + }); + + expect(result).toEqual({ allowed: false, reason: "group-override-unauthorized" }); + }); + + it("allows group message when override is not configured", () => { + const result = evaluateTelegramGroupBaseAccess({ + isGroup: true, + hasGroupAllowOverride: false, + effectiveGroupAllow: allow([]), + senderId: "12345", + senderUsername: "tester", + enforceAllowOverride: true, + requireSenderForAllowOverride: true, + }); + + expect(result).toEqual({ allowed: true }); + }); + + it("allows sender explicitly listed in override", () => { + const result = evaluateTelegramGroupBaseAccess({ + isGroup: true, + hasGroupAllowOverride: true, + effectiveGroupAllow: allow(["12345"]), + senderId: "12345", + senderUsername: "tester", + enforceAllowOverride: true, + requireSenderForAllowOverride: true, + }); + + expect(result).toEqual({ allowed: true }); + }); +}); diff --git a/src/telegram/group-access.ts b/src/telegram/group-access.ts index dcd0dd2ef6e..1702277da6b 100644 --- a/src/telegram/group-access.ts +++ b/src/telegram/group-access.ts @@ -42,6 +42,11 @@ export const evaluateTelegramGroupBaseAccess = (params: { return { allowed: true }; } + // Explicit per-group/topic allowFrom override must fail closed when empty. + if (!params.effectiveGroupAllow.hasEntries) { + return { allowed: false, reason: "group-override-unauthorized" }; + } + const senderId = params.senderId ?? ""; if (params.requireSenderForAllowOverride && !senderId) { return { allowed: false, reason: "group-override-unauthorized" };