Skip to content

dmPolicy allowFrom not enforced for Telegram text messages — unauthorized users reach agents #91209

@producedbysavant

Description

@producedbysavant

Summary

dmPolicy: "allowlist" + allowFrom does not prevent text messages from unauthorized Telegram users from reaching bound agents. The DM access check in bot-handlers.runtime.ts is gated behind hasInboundMedia, allowing plain text messages to bypass ingress filtering entirely.

Version

v2026.6.1 (latest stable) — installed via npm, running on Node.js v24.15.0, Bun binary runtime.

Configuration

"channels": {
  "telegram": {
    "dmPolicy": "allowlist",
    "allowFrom": ["1144466778"],
    "groupPolicy": "allowlist",
    "groupAllowFrom": ["1144466778"]
  }
}

Reproduction

  1. Configure dmPolicy: "allowlist" with allowFrom: ["<owner_id>"]
  2. Have a non-allowlisted user send a plain text DM (no media, no reply-to-media) to the bot
  3. The message reaches the bound agent, which processes it and generates a reply
  4. Delivery fails with 400: chat not found because bot hasn't started DM with the unauthorized user
  5. Failed delivery enters send_attempt_started state and blocks reconnect drain with refusing blind replay without adapter reconciliation

Root Cause

Two call sites for enforceTelegramDmAccess:

1. extensions/telegram/src/bot-handlers.runtime.ts:2847 — BUGGY GATE

if (!event.isGroup && (hasInboundMedia(event.msg) || hasReplyTargetMedia(event.msg))) {
    if (!await enforceTelegramDmAccess({...})) return;
}

DM access is ONLY checked for messages with media or reply-to-media. Plain text messages skip this check entirely and proceed directly to processInboundMessage → agent dispatch.

2. extensions/telegram/src/bot-message-context.ts:361 — CONTEXT BUILDER GATE

if (!await enforceTelegramDmAccess({...})) return null;

This is unconditional and SHOULD block unauthorized senders before dispatchTelegramMessage. However, it does not prevent the agent from processing the message and spending tokens — it only prevents the dispatch. In practice, unauthorized users still reach agent processing.

Impact (measured over 13 days on a production instance)

Metric Value
Failed deliveries in DB 1,884
Unique unauthorized targets 72
Entries NOT in allowFrom 1,876 / 1,884 (99.6%)
Top spurious target Bot's own ID (8243344628): 845 entries
Time span 2026-05-24 to 2026-06-05
Peak day June 4: 406 entries

Secondary effects

  • Token waste: every foreign message consumes DeepSeek API tokens for processing + reply generation
  • Delivery queue pollution: 1,884 stuck entries block the Telegram reconnect drain with refusing blind replay without adapter reconciliation
  • Session corruption: concurrent session access from foreign messages triggers EmbeddedAttemptSessionTakeoverError
  • Legitimate message delay: reconnect drain retries block delivery of legitimate owner messages

Related

Expected Behavior

Messages from users NOT in allowFrom should be silently dropped at the channel ingress level — before any agent dispatch, token consumption, or reply generation. The enforceTelegramDmAccess call in bot-handlers.runtime.ts:2847 should NOT be gated behind hasInboundMedia.

Suggested Fix

Remove the hasInboundMedia gate in bot-handlers.runtime.ts:

- if (!event.isGroup && (hasInboundMedia(event.msg) || hasReplyTargetMedia(event.msg))) {
-     if (!await enforceTelegramDmAccess({...})) return;
- }
+ if (!event.isGroup) {
+     if (!await enforceTelegramDmAccess({...})) return;
+ }

The context builder gate in bot-message-context.ts serves as a second line of defense for any paths that might bypass the handler-level check.

Metadata

Metadata

Assignees

Labels

P1High-priority user-facing bug, regression, or broken workflow.clawsweeper:needs-live-reproClawSweeper needs live local, crabbox, or manual validation to confirm this issue.clawsweeper:needs-maintainer-reviewClawSweeper marked this issue as needing maintainer review before automation.clawsweeper:needs-security-reviewClawSweeper marked this issue as needing security-sensitive review.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.impact:message-lossChannel message delivery can be lost, duplicated, or misrouted.impact:securitySecurity boundary, credential, authz, sandbox, or sensitive-data risk.impact:session-stateSession, memory, transcript, context, or agent state can drift or corrupt.issue-rating: 🐚 platinum hermitGood issue quality with a plausible reproduction path needing some confirmation.

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions