Telegram channel: /start, /help, /status commands bypass gate() and respond to non-allowlisted users
Bug
The Telegram channel plugin registers /start, /help, and /status as bot commands before the shared message handler where gate() runs. This means these commands respond to any Telegram user, even when dmPolicy is set to "allowlist" or "disabled".
In practice, a stranger who finds the bot can run /start and learn they've found a Claude Code bridge, or /help to see pairing instructions — even though gate() would have blocked their regular messages.
Impact
- Information disclosure: Non-allowlisted users learn that a bot token belongs to a Claude Code Telegram bridge
- Leaks pairing instructions:
/starttells strangers exactly how to attempt pairing, even under"allowlist"mode where no new pairings should be possible
Steps to reproduce
- Set up the Telegram channel with
dmPolicy: "allowlist"and a specificallowFromlist - From a Telegram account not in the allowlist, send
/startor/helpto the bot - The bot responds with pairing instructions and bridge details, instead of staying silent
Fix
Add a guard check to each command handler that silently returns for non-allowlisted users when dmPolicy is not "pairing". Under "pairing" mode, /start should still respond (that's how new users learn to pair).
function commandMuted(ctx: Context, access: Access): boolean {
if (access.dmPolicy === 'pairing') return false
const from = ctx.from
if (!from) return true
return !access.allowFrom.includes(String(from.id))
}
Then at the top of each command handler:
bot.command('start', async ctx => {
if (ctx.chat?.type !== 'private') return
const access = loadAccess()
if (commandMuted(ctx, access)) return // ← added
// ...
})
Same pattern for /help and /status.
This is a +15 line patch with no deletions. I've been running this fix in production since 2026-08-25.
Reference implementation: https://github.com/Swigler/claude-telegram-bridge