Skip to content

Telegram native command handler ignores commands.allowFrom in group chats #28216

@toolsbybuddy

Description

@toolsbybuddy

Bug Description

Telegram native slash commands (/status, /models, etc.) return "You are not authorized to use this command." in group chats, even when the sender is explicitly listed in commands.allowFrom.telegram. The same commands work correctly in DMs.

Root Cause

There are two separate command authorization code paths:

  1. Text command handler (resolveCommandAuthorization in auto-reply/reply) — correctly resolves commands.allowFrom via resolveCommandsAllowFromList() and uses it as the sole authority when configured ✅
  2. Telegram native command handler (resolveTelegramCommandAuth in telegram/bot-native-commands.ts) — does not check commands.allowFrom at all ❌ — it only evaluates channel-level allowFrom + the pairing store via normalizeDmAllowFromWithStore

The docs for commands.allowFrom state:

When configured, it is the only authorization source for commands and directives (channel allowlists/pairing and useAccessGroups are ignored).

This contract is honored by the text command path but not by the native Telegram command path.

Steps to Reproduce

  1. Configure commands.allowFrom with your Telegram user IDs:
{
  "commands": {
    "allowFrom": {
      "telegram": ["123456789"],
      "*": ["123456789"]
    }
  },
  "channels": {
    "telegram": {
      "groupPolicy": "open"
      // Note: no channels.telegram.allowFrom set
    }
  }
}
  1. Send /status in a DM → works ✅
  2. Send /status in a group chat → "You are not authorized to use this command." ❌

Why It Surfaces Now

The breaking change in 2026.2.25 (#25988) removed the DM pairing-store fallback for group sender authorization:

Security/Telegram group allowlist: fail closed for group sender authorization by removing DM pairing-store fallback from group allowlist evaluation

In the native command handler, this means storeAllowFrom is [] for groups. Combined with no channels.telegram.allowFrom being set, the handler sees zero authorized entries and rejects the sender — even though commands.allowFrom explicitly authorizes them.

Before 2026.2.25, the pairing store fallback masked this gap.

Code References (2026.2.26)

In pi-embedded-CQnl8oWA.js:

  • Native handler (resolveTelegramCommandAuth, ~line 73597): builds dmAllow from channel-level allowFrom + pairing store only. Never calls resolveCommandsAllowFromList().
  • Text handler (resolveCommandAuthorization, ~line 10906): correctly calls resolveCommandsAllowFromList() and when commandsAllowFromList !== null, uses it as the sole authority.

Expected Behavior

resolveTelegramCommandAuth should check commands.allowFrom (via resolveCommandsAllowFromList or equivalent) before falling through to channel-level allowFrom / pairing store checks, consistent with the text command handler and the documented behavior.

Workaround

Add channels.telegram.allowFrom with the same user IDs. This feeds directly into the native handler:

{
  "channels": {
    "telegram": {
      "allowFrom": ["123456789"]
    }
  }
}

Environment

  • OpenClaw version: 2026.2.26
  • Channel: Telegram (polling mode)
  • OS: macOS (arm64)

Metadata

Metadata

Assignees

Labels

No labels
No labels

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