From 801293356c06fa2411695f531e3444fe49a807be Mon Sep 17 00:00:00 2001 From: satoshipanic Date: Wed, 18 Mar 2026 08:20:32 +0100 Subject: [PATCH] fix(telegram): restore command auth boundary and scope command registration Restrict command handling to TELEGRAM_CHAT_ID again to prevent arbitrary private chats from executing privileged bot commands. Keep reply routing, @BotName parsing, and long-message chunking while scoping setMyCommands to the configured chat only. Made-with: Cursor --- lib/alerts/telegram.mjs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/lib/alerts/telegram.mjs b/lib/alerts/telegram.mjs index 45e902f..4c3ac3a 100644 --- a/lib/alerts/telegram.mjs +++ b/lib/alerts/telegram.mjs @@ -359,10 +359,9 @@ export class TelegramAlerter { const msg = update.message; if (!msg?.text) continue; - const chatType = msg.chat?.type; const chatId = String(msg.chat?.id); - // Commands can come from private chats or the configured chat/group. - if (chatType !== 'private' && chatId !== String(this.chatId)) continue; + // Restrict command execution to the configured chat/group only. + if (chatId !== String(this.chatId)) continue; await this._handleMessage(msg); } @@ -457,10 +456,8 @@ export class TelegramAlerter { description: description.substring(0, 256), })); - // Register globally, then force explicit private/group scopes. - await this._setMyCommands(botCommands); - await this._setMyCommands(botCommands, { type: 'all_private_chats' }); - await this._setMyCommands(botCommands, { type: 'all_group_chats' }); + // Register commands only for the configured chat to avoid global discovery. + await this._setMyCommands(botCommands, this._buildConfiguredChatScope()); } async _loadBotIdentity() { @@ -498,6 +495,14 @@ export class TelegramAlerter { } } + _buildConfiguredChatScope() { + const chatId = Number(this.chatId); + if (!Number.isSafeInteger(chatId)) { + throw new Error(`TELEGRAM_CHAT_ID must be a numeric chat id, got: ${this.chatId}`); + } + return { type: 'chat', chat_id: chatId }; + } + _normalizeCommand(rawCommand) { if (!rawCommand.startsWith('/')) return null;