Skip to content

fix(telegram): use group allowlist for native command auth in groups#39267

Merged
vincentkoc merged 5 commits intoopenclaw:mainfrom
edwluo:fix/telegram-group-command-auth
Mar 8, 2026
Merged

fix(telegram): use group allowlist for native command auth in groups#39267
vincentkoc merged 5 commits intoopenclaw:mainfrom
edwluo:fix/telegram-group-command-auth

Conversation

@edwluo
Copy link
Copy Markdown
Contributor

@edwluo edwluo commented Mar 7, 2026

Summary

  • Native slash commands (/status, /model, /new, etc.) in Telegram supergroups and forum topics reject authorized senders with "You are not authorized to use this command." even when the sender is in groupAllowFrom.
  • Root cause: resolveTelegramCommandAuth only passes the DM allowlist as an authorizer to resolveCommandAuthorizedFromAuthorizers, ignoring effectiveGroupAllow.
  • Fix: add effectiveGroupAllow as a second authorizer when the message originates from a group. resolveCommandAuthorizedFromAuthorizers uses .some(), so either DM or group allowlist matching is sufficient and matches regular message auth behavior.

What changed

src/telegram/bot-native-commands.ts

// Before: only DM allowlist
authorizers: [{ configured: dmAllow.hasEntries, allowed: senderAllowed }],

// After: DM allowlist + group allowlist for group contexts
const groupSenderAllowed = isGroup
  ? isSenderAllowed({ allow: effectiveGroupAllow, senderId, senderUsername })
  : false;
authorizers: [
  { configured: dmAllow.hasEntries, allowed: senderAllowed },
  ...(isGroup
    ? [{ configured: effectiveGroupAllow.hasEntries, allowed: groupSenderAllowed }]
    : []),
],

What did NOT change

  • DM command authorization
  • commands.allowFrom precedence behavior
  • evaluateTelegramGroupBaseAccess and evaluateTelegramGroupPolicyAccess

Test plan

  • New regression test in src/telegram/bot-native-commands.group-auth.test.ts
  • Verified group native command auth when sender is only in group allowlist
  • Verified the test uses useAccessGroups: true so it exercises the actual bug path

Reproduction

  1. Configure a Telegram supergroup with groupAllowFrom: [userId] but no top-level allowFrom
  2. Send /status in a forum topic or group
  3. Before fix: "You are not authorized to use this command."
  4. After fix: command executes normally

Context

This bug is separate from commands.allowFrom precedence drift. Earlier attempts #29230 and #30272 covered the same root cause; this PR is the active fix path for the effectiveGroupAllow group-auth bug.

Fixes #30234
Related #29135
Related #28216

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 7, 2026

Greptile Summary

This PR fixes a bug where native Telegram slash commands (e.g. /status, /model) rejected authorized senders in supergroups when the sender was listed in groupAllowFrom but not in the DM-level allowFrom. The root cause was that resolveTelegramCommandAuth only passed the DM allowlist to resolveCommandAuthorizedFromAuthorizers, ignoring effectiveGroupAllow entirely for command authorization (even though the earlier evaluateTelegramGroupBaseAccess / evaluateTelegramGroupPolicyAccess calls already used it correctly).

Key changes:

  • bot-native-commands.ts: Appends effectiveGroupAllow as a second CommandAuthorizer entry when the message is from a group, mirroring how regular message auth works.
  • bot-native-commands.group-auth.test.ts: New test file for the group-auth scenario.

Issue found:

  • The first (positive) test case — "authorizes native commands in groups when sender is in groupAllowFrom" — uses the default useAccessGroups: false. Under that flag, resolveCommandAuthorizedFromAuthorizers takes the "configured" path: when no DM allowlist is configured, anyConfigured = false → the function returns true unconditionally, even without the fix. This means the test would have passed on the unpatched code, making it an ineffective regression guard. Adding useAccessGroups: true to that test is needed for it to actually exercise the bug path.

Confidence Score: 4/5

  • The implementation fix is correct and safe to merge; the test gap is a coverage concern but doesn't affect production behaviour.
  • The core fix in bot-native-commands.ts is logically sound and correctly mirrors existing group-auth behaviour elsewhere in the file. The only notable issue is that the primary positive test case doesn't use useAccessGroups: true, so it would have passed even on the pre-fix code — it doesn't actually guard against a regression of this specific bug. The production fix itself is correct.
  • src/telegram/bot-native-commands.group-auth.test.ts — the first test needs useAccessGroups: true to be a meaningful regression guard.

Last reviewed commit: a0abf3e

@edwluo edwluo force-pushed the fix/telegram-group-command-auth branch from a0abf3e to beaf15b Compare March 7, 2026 23:46
@edwluo
Copy link
Copy Markdown
Contributor Author

edwluo commented Mar 7, 2026

Good catch — updated the first test case to use useAccessGroups: true so it exercises the actual bug path. Force-pushed.

@vincentkoc vincentkoc self-assigned this Mar 8, 2026
edwluo and others added 4 commits March 7, 2026 16:41
Native slash commands (/status, /model, etc.) in Telegram supergroups
and forum topics reject authorized senders with "not authorized" even
when the sender is in groupAllowFrom.

The bug is in resolveTelegramCommandAuth — the final commandAuthorized
check only passes DM allowFrom as an authorizer, so senders who are
authorized via groupAllowFrom get rejected. Regular messages don't have
this problem because they go through evaluateTelegramGroupPolicyAccess
which correctly uses effectiveGroupAllow.

Add effectiveGroupAllow as a second authorizer when the message comes
from a group. resolveCommandAuthorizedFromAuthorizers uses .some(), so
either DM or group allowlist matching is sufficient.

Fixes #28216
Fixes #29135
Fixes #30234
Remove explicit tuple type annotations on mock.calls.filter() callbacks
that conflicted with vitest's mock call types.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
@vincentkoc vincentkoc force-pushed the fix/telegram-group-command-auth branch from d26991a to 18f0a7a Compare March 8, 2026 00:43
@vincentkoc
Copy link
Copy Markdown
Member

Rebased onto current main and tightened the coverage before merge.

What changed on top of the existing fix:

Re-ran:

  • bunx vitest run src/telegram/bot-native-commands.group-auth.test.ts src/telegram/bot-native-commands.session-meta.test.ts src/telegram/bot-native-commands.plugin-auth.test.ts

@vincentkoc vincentkoc merged commit 02eef1d into openclaw:main Mar 8, 2026
27 of 28 checks passed
vincentkoc added a commit to BryanTegomoh/openclaw-fork that referenced this pull request Mar 8, 2026
…penclaw#39267)

* fix(telegram): use group allowlist for native command auth in groups

Native slash commands (/status, /model, etc.) in Telegram supergroups
and forum topics reject authorized senders with "not authorized" even
when the sender is in groupAllowFrom.

The bug is in resolveTelegramCommandAuth — the final commandAuthorized
check only passes DM allowFrom as an authorizer, so senders who are
authorized via groupAllowFrom get rejected. Regular messages don't have
this problem because they go through evaluateTelegramGroupPolicyAccess
which correctly uses effectiveGroupAllow.

Add effectiveGroupAllow as a second authorizer when the message comes
from a group. resolveCommandAuthorizedFromAuthorizers uses .some(), so
either DM or group allowlist matching is sufficient.

Fixes openclaw#28216
Fixes openclaw#29135
Fixes openclaw#30234

* fix(test): resolve TS2769 type errors in group-auth test

Remove explicit tuple type annotations on mock.calls.filter() callbacks
that conflicted with vitest's mock call types.

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* test(telegram): cover topic auth rejection routing

* changelog: note telegram native group command auth fix

---------

Co-authored-by: Claude Opus 4.6 <[email protected]>
Co-authored-by: Vincent Koc <[email protected]>
ziomancer pushed a commit to ziomancer/openclaw that referenced this pull request Mar 8, 2026
…penclaw#39267)

* fix(telegram): use group allowlist for native command auth in groups

Native slash commands (/status, /model, etc.) in Telegram supergroups
and forum topics reject authorized senders with "not authorized" even
when the sender is in groupAllowFrom.

The bug is in resolveTelegramCommandAuth — the final commandAuthorized
check only passes DM allowFrom as an authorizer, so senders who are
authorized via groupAllowFrom get rejected. Regular messages don't have
this problem because they go through evaluateTelegramGroupPolicyAccess
which correctly uses effectiveGroupAllow.

Add effectiveGroupAllow as a second authorizer when the message comes
from a group. resolveCommandAuthorizedFromAuthorizers uses .some(), so
either DM or group allowlist matching is sufficient.

Fixes openclaw#28216
Fixes openclaw#29135
Fixes openclaw#30234

* fix(test): resolve TS2769 type errors in group-auth test

Remove explicit tuple type annotations on mock.calls.filter() callbacks
that conflicted with vitest's mock call types.

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* test(telegram): cover topic auth rejection routing

* changelog: note telegram native group command auth fix

---------

Co-authored-by: Claude Opus 4.6 <[email protected]>
Co-authored-by: Vincent Koc <[email protected]>
openperf pushed a commit to openperf/moltbot that referenced this pull request Mar 8, 2026
…penclaw#39267)

* fix(telegram): use group allowlist for native command auth in groups

Native slash commands (/status, /model, etc.) in Telegram supergroups
and forum topics reject authorized senders with "not authorized" even
when the sender is in groupAllowFrom.

The bug is in resolveTelegramCommandAuth — the final commandAuthorized
check only passes DM allowFrom as an authorizer, so senders who are
authorized via groupAllowFrom get rejected. Regular messages don't have
this problem because they go through evaluateTelegramGroupPolicyAccess
which correctly uses effectiveGroupAllow.

Add effectiveGroupAllow as a second authorizer when the message comes
from a group. resolveCommandAuthorizedFromAuthorizers uses .some(), so
either DM or group allowlist matching is sufficient.

Fixes openclaw#28216
Fixes openclaw#29135
Fixes openclaw#30234

* fix(test): resolve TS2769 type errors in group-auth test

Remove explicit tuple type annotations on mock.calls.filter() callbacks
that conflicted with vitest's mock call types.

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* test(telegram): cover topic auth rejection routing

* changelog: note telegram native group command auth fix

---------

Co-authored-by: Claude Opus 4.6 <[email protected]>
Co-authored-by: Vincent Koc <[email protected]>
mcaxtr pushed a commit to mcaxtr/openclaw that referenced this pull request Mar 8, 2026
…penclaw#39267)

* fix(telegram): use group allowlist for native command auth in groups

Native slash commands (/status, /model, etc.) in Telegram supergroups
and forum topics reject authorized senders with "not authorized" even
when the sender is in groupAllowFrom.

The bug is in resolveTelegramCommandAuth — the final commandAuthorized
check only passes DM allowFrom as an authorizer, so senders who are
authorized via groupAllowFrom get rejected. Regular messages don't have
this problem because they go through evaluateTelegramGroupPolicyAccess
which correctly uses effectiveGroupAllow.

Add effectiveGroupAllow as a second authorizer when the message comes
from a group. resolveCommandAuthorizedFromAuthorizers uses .some(), so
either DM or group allowlist matching is sufficient.

Fixes openclaw#28216
Fixes openclaw#29135
Fixes openclaw#30234

* fix(test): resolve TS2769 type errors in group-auth test

Remove explicit tuple type annotations on mock.calls.filter() callbacks
that conflicted with vitest's mock call types.

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* test(telegram): cover topic auth rejection routing

* changelog: note telegram native group command auth fix

---------

Co-authored-by: Claude Opus 4.6 <[email protected]>
Co-authored-by: Vincent Koc <[email protected]>
Saitop pushed a commit to NomiciAI/openclaw that referenced this pull request Mar 8, 2026
…penclaw#39267)

* fix(telegram): use group allowlist for native command auth in groups

Native slash commands (/status, /model, etc.) in Telegram supergroups
and forum topics reject authorized senders with "not authorized" even
when the sender is in groupAllowFrom.

The bug is in resolveTelegramCommandAuth — the final commandAuthorized
check only passes DM allowFrom as an authorizer, so senders who are
authorized via groupAllowFrom get rejected. Regular messages don't have
this problem because they go through evaluateTelegramGroupPolicyAccess
which correctly uses effectiveGroupAllow.

Add effectiveGroupAllow as a second authorizer when the message comes
from a group. resolveCommandAuthorizedFromAuthorizers uses .some(), so
either DM or group allowlist matching is sufficient.

Fixes openclaw#28216
Fixes openclaw#29135
Fixes openclaw#30234

* fix(test): resolve TS2769 type errors in group-auth test

Remove explicit tuple type annotations on mock.calls.filter() callbacks
that conflicted with vitest's mock call types.

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* test(telegram): cover topic auth rejection routing

* changelog: note telegram native group command auth fix

---------

Co-authored-by: Claude Opus 4.6 <[email protected]>
Co-authored-by: Vincent Koc <[email protected]>
GordonSH-oss pushed a commit to GordonSH-oss/openclaw that referenced this pull request Mar 9, 2026
…penclaw#39267)

* fix(telegram): use group allowlist for native command auth in groups

Native slash commands (/status, /model, etc.) in Telegram supergroups
and forum topics reject authorized senders with "not authorized" even
when the sender is in groupAllowFrom.

The bug is in resolveTelegramCommandAuth — the final commandAuthorized
check only passes DM allowFrom as an authorizer, so senders who are
authorized via groupAllowFrom get rejected. Regular messages don't have
this problem because they go through evaluateTelegramGroupPolicyAccess
which correctly uses effectiveGroupAllow.

Add effectiveGroupAllow as a second authorizer when the message comes
from a group. resolveCommandAuthorizedFromAuthorizers uses .some(), so
either DM or group allowlist matching is sufficient.

Fixes openclaw#28216
Fixes openclaw#29135
Fixes openclaw#30234

* fix(test): resolve TS2769 type errors in group-auth test

Remove explicit tuple type annotations on mock.calls.filter() callbacks
that conflicted with vitest's mock call types.

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* test(telegram): cover topic auth rejection routing

* changelog: note telegram native group command auth fix

---------

Co-authored-by: Claude Opus 4.6 <[email protected]>
Co-authored-by: Vincent Koc <[email protected]>
jenawant pushed a commit to jenawant/openclaw that referenced this pull request Mar 10, 2026
…penclaw#39267)

* fix(telegram): use group allowlist for native command auth in groups

Native slash commands (/status, /model, etc.) in Telegram supergroups
and forum topics reject authorized senders with "not authorized" even
when the sender is in groupAllowFrom.

The bug is in resolveTelegramCommandAuth — the final commandAuthorized
check only passes DM allowFrom as an authorizer, so senders who are
authorized via groupAllowFrom get rejected. Regular messages don't have
this problem because they go through evaluateTelegramGroupPolicyAccess
which correctly uses effectiveGroupAllow.

Add effectiveGroupAllow as a second authorizer when the message comes
from a group. resolveCommandAuthorizedFromAuthorizers uses .some(), so
either DM or group allowlist matching is sufficient.

Fixes openclaw#28216
Fixes openclaw#29135
Fixes openclaw#30234

* fix(test): resolve TS2769 type errors in group-auth test

Remove explicit tuple type annotations on mock.calls.filter() callbacks
that conflicted with vitest's mock call types.

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* test(telegram): cover topic auth rejection routing

* changelog: note telegram native group command auth fix

---------

Co-authored-by: Claude Opus 4.6 <[email protected]>
Co-authored-by: Vincent Koc <[email protected]>
@SanderHelgesen
Copy link
Copy Markdown

Still reproducing on 2026.3.8 with groupPolicy: "open" and no groupAllowFrom set.

Config:

{
  "channels": {
    "telegram": {
      "groupPolicy": "open",
      "groups": {
        "-100xxx": {
          "requireMention": false,
          "topics": { ... }
        }
      }
    }
  }
}

Native commands (/status, /elevated, /commands) in forum topics still return "You are not authorized to use this command." — the fix seems to only resolve the case where groupAllowFrom is explicitly configured. When groupPolicy: "open" is used without an allowlist, the group authorizer has configured: false and resolveCommandAuthorizedFromAuthorizers still denies.

Paired DM user (owner) is authorized for everything in DMs and regular group messages work fine — only native slash commands are rejected.

+1 on reopening or tracking separately.

dhoman pushed a commit to dhoman/chrono-claw that referenced this pull request Mar 11, 2026
…penclaw#39267)

* fix(telegram): use group allowlist for native command auth in groups

Native slash commands (/status, /model, etc.) in Telegram supergroups
and forum topics reject authorized senders with "not authorized" even
when the sender is in groupAllowFrom.

The bug is in resolveTelegramCommandAuth — the final commandAuthorized
check only passes DM allowFrom as an authorizer, so senders who are
authorized via groupAllowFrom get rejected. Regular messages don't have
this problem because they go through evaluateTelegramGroupPolicyAccess
which correctly uses effectiveGroupAllow.

Add effectiveGroupAllow as a second authorizer when the message comes
from a group. resolveCommandAuthorizedFromAuthorizers uses .some(), so
either DM or group allowlist matching is sufficient.

Fixes openclaw#28216
Fixes openclaw#29135
Fixes openclaw#30234

* fix(test): resolve TS2769 type errors in group-auth test

Remove explicit tuple type annotations on mock.calls.filter() callbacks
that conflicted with vitest's mock call types.

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* test(telegram): cover topic auth rejection routing

* changelog: note telegram native group command auth fix

---------

Co-authored-by: Claude Opus 4.6 <[email protected]>
Co-authored-by: Vincent Koc <[email protected]>
senw-developers pushed a commit to senw-developers/va-openclaw that referenced this pull request Mar 17, 2026
…penclaw#39267)

* fix(telegram): use group allowlist for native command auth in groups

Native slash commands (/status, /model, etc.) in Telegram supergroups
and forum topics reject authorized senders with "not authorized" even
when the sender is in groupAllowFrom.

The bug is in resolveTelegramCommandAuth — the final commandAuthorized
check only passes DM allowFrom as an authorizer, so senders who are
authorized via groupAllowFrom get rejected. Regular messages don't have
this problem because they go through evaluateTelegramGroupPolicyAccess
which correctly uses effectiveGroupAllow.

Add effectiveGroupAllow as a second authorizer when the message comes
from a group. resolveCommandAuthorizedFromAuthorizers uses .some(), so
either DM or group allowlist matching is sufficient.

Fixes openclaw#28216
Fixes openclaw#29135
Fixes openclaw#30234

* fix(test): resolve TS2769 type errors in group-auth test

Remove explicit tuple type annotations on mock.calls.filter() callbacks
that conflicted with vitest's mock call types.

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* test(telegram): cover topic auth rejection routing

* changelog: note telegram native group command auth fix

---------

Co-authored-by: Claude Opus 4.6 <[email protected]>
Co-authored-by: Vincent Koc <[email protected]>
V-Gutierrez pushed a commit to V-Gutierrez/openclaw-vendor that referenced this pull request Mar 17, 2026
…penclaw#39267)

* fix(telegram): use group allowlist for native command auth in groups

Native slash commands (/status, /model, etc.) in Telegram supergroups
and forum topics reject authorized senders with "not authorized" even
when the sender is in groupAllowFrom.

The bug is in resolveTelegramCommandAuth — the final commandAuthorized
check only passes DM allowFrom as an authorizer, so senders who are
authorized via groupAllowFrom get rejected. Regular messages don't have
this problem because they go through evaluateTelegramGroupPolicyAccess
which correctly uses effectiveGroupAllow.

Add effectiveGroupAllow as a second authorizer when the message comes
from a group. resolveCommandAuthorizedFromAuthorizers uses .some(), so
either DM or group allowlist matching is sufficient.

Fixes openclaw#28216
Fixes openclaw#29135
Fixes openclaw#30234

* fix(test): resolve TS2769 type errors in group-auth test

Remove explicit tuple type annotations on mock.calls.filter() callbacks
that conflicted with vitest's mock call types.

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* test(telegram): cover topic auth rejection routing

* changelog: note telegram native group command auth fix

---------

Co-authored-by: Claude Opus 4.6 <[email protected]>
Co-authored-by: Vincent Koc <[email protected]>
alexey-pelykh pushed a commit to remoteclaw/remoteclaw that referenced this pull request Mar 22, 2026
…penclaw#39267)

* fix(telegram): use group allowlist for native command auth in groups

Native slash commands (/status, /model, etc.) in Telegram supergroups
and forum topics reject authorized senders with "not authorized" even
when the sender is in groupAllowFrom.

The bug is in resolveTelegramCommandAuth — the final commandAuthorized
check only passes DM allowFrom as an authorizer, so senders who are
authorized via groupAllowFrom get rejected. Regular messages don't have
this problem because they go through evaluateTelegramGroupPolicyAccess
which correctly uses effectiveGroupAllow.

Add effectiveGroupAllow as a second authorizer when the message comes
from a group. resolveCommandAuthorizedFromAuthorizers uses .some(), so
either DM or group allowlist matching is sufficient.

Fixes openclaw#28216
Fixes openclaw#29135
Fixes openclaw#30234

* fix(test): resolve TS2769 type errors in group-auth test

Remove explicit tuple type annotations on mock.calls.filter() callbacks
that conflicted with vitest's mock call types.

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* test(telegram): cover topic auth rejection routing

* changelog: note telegram native group command auth fix

---------

Co-authored-by: Claude Opus 4.6 <[email protected]>
Co-authored-by: Vincent Koc <[email protected]>
(cherry picked from commit 02eef1d)
alexey-pelykh pushed a commit to remoteclaw/remoteclaw that referenced this pull request Mar 22, 2026
…penclaw#39267)

* fix(telegram): use group allowlist for native command auth in groups

Native slash commands (/status, /model, etc.) in Telegram supergroups
and forum topics reject authorized senders with "not authorized" even
when the sender is in groupAllowFrom.

The bug is in resolveTelegramCommandAuth — the final commandAuthorized
check only passes DM allowFrom as an authorizer, so senders who are
authorized via groupAllowFrom get rejected. Regular messages don't have
this problem because they go through evaluateTelegramGroupPolicyAccess
which correctly uses effectiveGroupAllow.

Add effectiveGroupAllow as a second authorizer when the message comes
from a group. resolveCommandAuthorizedFromAuthorizers uses .some(), so
either DM or group allowlist matching is sufficient.

Fixes openclaw#28216
Fixes openclaw#29135
Fixes openclaw#30234

* fix(test): resolve TS2769 type errors in group-auth test

Remove explicit tuple type annotations on mock.calls.filter() callbacks
that conflicted with vitest's mock call types.

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* test(telegram): cover topic auth rejection routing

* changelog: note telegram native group command auth fix

---------

Co-authored-by: Claude Opus 4.6 <[email protected]>
Co-authored-by: Vincent Koc <[email protected]>
(cherry picked from commit 02eef1d)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: telegram Channel integration: telegram size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Telegram native command auth in groups checks DM allowlist instead of groupAllowFrom

3 participants