Skip to content

fix(telegram): use group allowFrom for commands in groups#29175

Open
ivelin wants to merge 2 commits intoopenclaw:mainfrom
ivelin:fix/telegram-group-command-auth
Open

fix(telegram): use group allowFrom for commands in groups#29175
ivelin wants to merge 2 commits intoopenclaw:mainfrom
ivelin:fix/telegram-group-command-auth

Conversation

@ivelin
Copy link
Copy Markdown

@ivelin ivelin commented Feb 27, 2026

Summary

Describe the problem and fix in 2–5 bullets:

  • Problem: Telegram slash commands stopped working in group topics after 2026.2.25+ security update
  • Why it matters: Users couldn't use /help, /status, or other commands in group topics
  • What changed: Command authorization now uses group allowFrom for groups, DM allowFrom for DMs
  • What did NOT change (scope boundary): DM command authorization unchanged; security boundary between DM and group auth preserved

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

User-visible / Behavior Changes

  • Slash commands now work in Telegram group topics
  • Users in DM allowFrom but NOT in group allowFrom are properly blocked in groups
  • If none, write None.

Security Impact (required)

  • New permissions/capabilities? (No)
  • Secrets/tokens handling changed? (No)
  • New/changed network calls? (No)
  • Command/tool execution surface changed? (No - only auth logic)
  • Data access scope changed? (No)
  • If any Yes, explain risk + mitigation: N/A

Repro + Verification

Environment

  • OS: Linux (spark-9045)
  • Runtime/container: OpenClaw gateway
  • Model/provider: MiniMax via OpenRouter
  • Integration/channel (if any): Telegram group topics
  • Relevant config (redacted): group allowFrom configured with user IDs

Steps

  1. Configure group allowFrom in telegram config (e.g., allowFrom: [<telegram_ID>])
  2. Send slash command (/help, /status) in group topic
  3. Observe command not being processed (before fix)

Expected

  • Command is authorized and processed

Actual (before fix)

  • Command blocked with "You are not authorized to use this command"

Evidence

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

What you personally verified (and how):

  • Verified scenarios: Sent /help command in Telegram group topic - now works
  • Edge cases checked: Users in DM allowFrom but NOT group allowFrom are blocked in groups
  • What you did not verify: Multiple group configs, topic-specific allowFrom

Compatibility / Migration

  • Backward compatible? (Yes)
  • Config/env changes? (No - existing group allowFrom now works for commands)
  • Migration needed? (No)
  • If yes, exact upgrade steps: N/A

Failure Recovery (if this breaks)

  • How to disable/revert this change quickly: Revert commit 7aef222 or disable useAccessGroups
  • Files/config to restore: src/telegram/bot-native-commands.ts
  • Known bad symptoms reviewers should watch for: Commands in DMs stop working

Risks and Mitigations

List only real risks for this PR:

  • Risk: None identified - this restores previously working behavior
  • Mitigation: N/A

Previously, telegram native commands in groups were authorized using the
DM allowFrom config instead of the group allowFrom config. This was a
regression introduced in the security hardening that separated group
auth from DM pairing-store (commit 64de4b6).

This fix ensures that:
- Commands in groups use group allowFrom (or groupAllowFrom)
- Commands in DMs continue to use DM allowFrom
- Users in DM allowFrom but NOT in group allowFrom are properly
  blocked in groups

Fixes regression where slash commands stopped working in group topics
after 2026.2.25+ security update.

Added regression tests in bot-native-commands.group-auth.test.ts
@openclaw-barnacle openclaw-barnacle bot added channel: telegram Channel integration: telegram size: M labels Feb 27, 2026
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Feb 27, 2026

Greptile Summary

Fixed authorization bug where Telegram slash commands incorrectly used DM allowFrom for group authorization instead of group allowFrom, allowing unauthorized users to execute commands in groups.

  • Root cause: Command authorization was using normalizeDmAllowFromWithStore with DM allowFrom for both DMs and groups
  • Fix: Commands now use effectiveGroupAllow (group-specific allowFrom) for groups and DM allowFrom for DMs via ternary operator
  • Impact: Users in DM allowFrom but not in group allowFrom are now properly blocked from executing commands in groups
  • Alignment: Brings command authorization in line with existing message authorization logic in bot-handlers.ts which already correctly separates DM and group contexts
  • Testing: Added comprehensive regression tests covering both the bug scenario (user in DM allowFrom blocked in groups) and the correct scenario (user in group allowFrom allowed in groups)

Confidence Score: 5/5

  • This PR is safe to merge with no identified risks - it fixes an authorization bypass and includes comprehensive tests
  • The fix is minimal (8 lines changed), well-tested with regression coverage, and actually improves security by fixing an authorization bypass where DM users could execute commands in groups. The logic correctly separates DM and group authorization contexts, matching the existing pattern used in message handling. The change restores previously working behavior that regressed in a recent security update.
  • No files require special attention

Last reviewed commit: 7aef222

@ivelin
Copy link
Copy Markdown
Author

ivelin commented Feb 27, 2026

FYI, CI failure is not related to this PR.


> [email protected] lint /home/runner/_work/openclaw/openclaw
> oxlint --type-aware


  × typescript-eslint(no-unnecessary-type-assertion): This assertion is unnecessary since it does not change the type of the expression.
     ╭─[src/cli/daemon-cli/status.print.ts:217:53]
 216 │       service.runtime,
 217 │       (service.command?.environment ?? process.env) as NodeJS.ProcessEnv,
     ·        ─────────────────────┬─────────────────────  ──────────┬──────────
     ·                             │                                 ╰── Casting it to 'ProcessEnv' is unnecessary
     ·                             ╰── This expression already has the type 'ProcessEnv'
 218 │     )) {
     ╰────

  × typescript-eslint(no-unnecessary-type-assertion): This assertion is unnecessary since it does not change the type of the expression.
     ╭─[src/cli/daemon-cli/status.print.ts:225:63]
 224 │   if (service.runtime?.cachedLabel) {
 225 │     const env = (service.command?.environment ?? process.env) as NodeJS.ProcessEnv;
     ·                  ─────────────────────┬─────────────────────  ──────────┬──────────
     ·                                       │                                 ╰── Casting it to 'ProcessEnv' is unnecessary
     ·                                       ╰── This expression already has the type 'ProcessEnv'
 226 │     const labelValue = resolveGatewayLaunchAgentLabel(env.OPENCLAW_PROFILE);
     ╰────

  × typescript-eslint(no-unnecessary-type-assertion): This assertion is unnecessary since it does not change the type of the expression.
     ╭─[src/cli/daemon-cli/status.print.ts:268:65]
 267 │     if (process.platform === "linux") {
 268 │       const env = (service.command?.environment ?? process.env) as NodeJS.ProcessEnv;
     ·                    ─────────────────────┬─────────────────────  ──────────┬──────────
     ·                                         │                                 ╰── Casting it to 'ProcessEnv' is unnecessary
     ·                                         ╰── This expression already has the type 'ProcessEnv'
 269 │       const unit = resolveGatewaySystemdServiceName(env.OPENCLAW_PROFILE);
     ╰────

  × typescript-eslint(no-unnecessary-type-assertion): This assertion is unnecessary since it does not change the type of the expression.
     ╭─[src/cli/daemon-cli/status.print.ts:275:55]
 274 │       const logs = resolveGatewayLogPaths(
 275 │         (service.command?.environment ?? process.env) as NodeJS.ProcessEnv,
     ·          ─────────────────────┬─────────────────────  ──────────┬──────────
     ·                               │                                 ╰── Casting it to 'ProcessEnv' is unnecessary
     ·                               ╰── This expression already has the type 'ProcessEnv'
 276 │       );
     ╰────

Found 0 warnings and 4 errors.
Finished in 3.2s on 4196 files with 136 rules using 20 threads.
 ELIFECYCLE  Command failed with exit code 1.
 ELIFECYCLE  Command failed with exit code 1.
Error: Process completed with exit code 1.

@openclaw-barnacle
Copy link
Copy Markdown

This pull request has been automatically marked as stale due to inactivity.
Please add updates or it will be closed.

@openclaw-barnacle openclaw-barnacle bot added the stale Marked as stale due to inactivity label Mar 5, 2026
@openclaw-barnacle openclaw-barnacle bot removed the stale Marked as stale due to inactivity label Mar 28, 2026
@openclaw-barnacle
Copy link
Copy Markdown

This pull request has been automatically marked as stale due to inactivity.
Please add updates or it will be closed.

@openclaw-barnacle openclaw-barnacle bot added the stale Marked as stale due to inactivity label Apr 2, 2026
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: M stale Marked as stale due to inactivity

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Telegram forum supergroup messages not reaching gateway at all (DM works)

1 participant