Skip to content

fix(telegram): parse ALLOW_ALL_USERS as boolean so an explicit false unblocks DM pairing - #68823

Open
PRATHAMESH75 wants to merge 2 commits into
NousResearch:mainfrom
PRATHAMESH75:fix/telegram-allow-all-false-not-configured
Open

fix(telegram): parse ALLOW_ALL_USERS as boolean so an explicit false unblocks DM pairing#68823
PRATHAMESH75 wants to merge 2 commits into
NousResearch:mainfrom
PRATHAMESH75:fix/telegram-allow-all-false-not-configured

Conversation

@PRATHAMESH75

Copy link
Copy Markdown
Contributor

What

The Telegram intake prefilter (_telegram_auth_env_configured, introduced in #54164 for #40863) decided whether auth was "configured" by testing every auth env var — including the *_ALLOW_ALL_USERS toggles — for a non-empty string. So an explicit GATEWAY_ALLOW_ALL_USERS=false (a common .env / config-template default) counted as configured, the prefilter consulted the runner's allowlist for an unknown DM sender, and the message was dropped before the pairing flow could run:

WARNING [Telegram] Blocked unauthorized user <id> in chat <id>

The victim never received a pairing code. An unset key and a false key are semantically identical everywhere else in the gateway — including _is_user_authorized (adapter.py:920) which already parses GATEWAY_ALLOW_ALL_USERS as a boolean, and the Discord adapter.

Fix

Split the keys in _telegram_auth_env_configured:

  • allowlist keys (TELEGRAM_ALLOWED_USERS, TELEGRAM_GROUP_ALLOWED_USERS, TELEGRAM_GROUP_ALLOWED_CHATS, GATEWAY_ALLOWED_USERS) — carry identities/chats, so any non-empty value still counts as configured.
  • *_ALLOW_ALL_USERS toggles — parsed as booleans (truthy in {true, 1, yes}), matching the existing parse at adapter.py:920 and the Discord adapter.

An explicit false now reads as not configured, so unknown DMs fall through to pairing as the docstring already promises.

Tests

tests/gateway/test_telegram_auth_check.py:

  • test_allow_all_users_false_is_not_configuredfalse/False/0/no/"" ALLOW_ALL toggles → not configured; true → configured; a real allowlist value → still configured.
  • test_unknown_dm_reaches_pairing_when_allow_all_is_false — end-to-end: with only GATEWAY_ALLOW_ALL_USERS=false, an unknown DM reaches pairing (True) and the runner allowlist is never consulted.

Both fail on main and pass with the fix. Preflight (windows-footguns, ruff, affected tests) green.

Fixes #68794

The arm64-fork-Docker CI job is expected to fail on fork PRs and is unrelated to this change.

@alt-glitch alt-glitch added type/bug Something isn't working P3 Low — cosmetic, nice to have comp/plugins Plugin system and bundled plugins platform/telegram Telegram bot adapter area/auth Authentication, OAuth, credential pools sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data labels Jul 21, 2026

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the focused Telegram regression fix. The premise remains present on current main: plugins/platforms/telegram/adapter.py:1014-1022 treats a non-empty GATEWAY_ALLOW_ALL_USERS=false as configured, and :1074-1083 then invokes runner authorization before the normal pairing path.

Problems

  • tests/gateway/test_telegram_auth_check.py:304-330 is described as end-to-end, but it calls _is_user_authorized_from_message() directly with a fake Runner. It does not exercise the real unauthorized-DM path, which generates and sends the pairing code in gateway/run.py:11531-11560.

Suggested changes

  • Add a real-runner regression covering GATEWAY_ALLOW_ALL_USERS=false and asserting pairing-code generation/delivery. The focused boolean-matrix test is still useful.

This is an automated hermes-sweeper review.

assert adapter._telegram_auth_env_configured() is True


def test_unknown_dm_reaches_pairing_when_allow_all_is_false(monkeypatch):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test is an adapter-level unit test, not end-to-end: the fake Runner proves the prefilter bypasses its authorization method, but it never executes GatewayRunner's unauthorized-DM branch that generates and sends a pairing code. Please add a real-runner regression for that delivery path.

@teknium1 teknium1 added sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 30, 2026
@PRATHAMESH75
PRATHAMESH75 force-pushed the fix/telegram-allow-all-false-not-configured branch 3 times, most recently from 4ffcd03 to c635174 Compare August 2, 2026 02:37
@PRATHAMESH75

Copy link
Copy Markdown
Contributor Author

Thanks — good catch. You're right that test_unknown_dm_reaches_pairing_when_allow_all_is_false only asserted the adapter prefilter returns True; it never drove GatewayRunner's unauthorized-DM branch, so the pairing-code generation/delivery path was uncovered.

Added a real-runner regression, test_allow_all_false_unknown_dm_reaches_real_runner_pairing, in tests/gateway/test_telegram_auth_check.py (head b8874b8). It builds a real GatewayRunner, sets only GATEWAY_ALLOW_ALL_USERS=false, feeds an unknown Telegram DM through _handle_message, and asserts the pairing branch actually fires — pairing_store.generate_code is called and the adapter delivers the code. This also exercises the runner-side toggle parse (authz_mixin._is_user_authorized treats false as unauthorized at gateway/authz_mixin.py:671), so the whole intake→pairing path is now covered end-to-end.

Kept the focused boolean-matrix and adapter-prefilter tests as you suggested — they stay useful for the narrow parse contract.

@GottZ

GottZ commented Aug 3, 2026

Copy link
Copy Markdown

This was generated by AI during triage.

Summary

One PR addresses issue #68794. #68823 changes Telegram’s auth-prefilter configuration check so false-valued *_ALLOW_ALL_USERS flags no longer count as configured auth, while preserving non-empty checks for actual allowlists; its tests cover the boolean matrix, prefilter bypass, and real-runner pairing-code generation and delivery.

Related pull requests

  • fix(telegram): parse ALLOW_ALL_USERS as boolean so an explicit false unblocks DM pairing #68823 best fix — (+189/-5) — n/a: The production diff directly separates string-valued allowlists from boolean *_ALLOW_ALL_USERS flags, parsing only {true, 1, yes} as enabled so an explicit false lets unknown DMs reach pairing. The visible keep_open review requested a real-GatewayRunner regression; the current diff adds that test and asserts both pairing-code generation and adapter delivery, but no revised contributor review is shown.

Suggested consolidation

Keep #68823 open with a salvage path: retain the focused parser fix, boolean-matrix coverage, and new real-runner pairing regression, and request contributor re-review because the current diff addresses the concrete gap identified by the still-visible keep_open review. There are no duplicate PRs to close.

Complex graph

flowchart LR
    classDef open fill:#dbeafe,stroke:#1d4ed8,color:#1e3a8a
    classDef merged fill:#dcfce7,stroke:#15803d,color:#14532d
    classDef closed fill:#e5e7eb,stroke:#6b7280,color:#1f2937
    classDef unverified fill:#f3f4f6,stroke:#9ca3af,color:#374151
    classDef best stroke-width:3px,stroke:#b45309
    classDef target stroke-width:3px,stroke:#4338ca
    I68794(["issue #68794 (open)"])
    P68823["PR #68823 (open)"]
    P68823 -->|best fix| I68794
    class I68794 open
    class P68823 open
    class P68823 best
    class P68823 target
    click I68794 "https://github.com/NousResearch/hermes-agent/issues/68794"
    click P68823 "https://github.com/NousResearch/hermes-agent/pull/68823"
Loading

Graph: solid arrow = fixes / best fix, dashed arrow = partial or unverified (see edge label); boxed group = PRs duplicating each other; amber border = best fix; indigo border = target; gray node = closed (state tag in the node label).

Cross-PR triage: Reviewed 1 pull request and 1 issue in this complex. Each diff was read against this issue; Assessment working set: 10 kB of PR diffs, 6 kB of issue/PR text, 5 kB of discussion (5 comments), 2 verify verdicts. verdicts reflect diff content, not PR titles. Part of an automated triage batch.

…unblocks DM pairing

The intake prefilter's _telegram_auth_env_configured() tested every auth env
var — including the *_ALLOW_ALL_USERS toggles — for a non-empty string. A
literal GATEWAY_ALLOW_ALL_USERS=false (a common .env / config-template default)
therefore counted as 'auth configured', so the prefilter consulted the runner's
allowlist for an unknown DM sender and dropped it before the pairing flow could
run — the victim never got a pairing code. An unset key and a false key are
semantically identical everywhere else in the gateway.

Split the keys: allowlist keys (identities/chats) still count as configured on
any non-empty value, but the *_ALLOW_ALL_USERS booleans are parsed as booleans
(truthy in {true,1,yes}), matching the existing parse in _is_user_authorized and
the Discord adapter. An explicit false now reads as not configured, so unknown
DMs fall through to pairing as documented.

Fixes NousResearch#68794
…_ALL=false (NousResearch#68794)

Add a GatewayRunner-level regression that drives an unknown Telegram DM
through _handle_message with only GATEWAY_ALLOW_ALL_USERS=false set, and
asserts the pairing branch actually generates and delivers a code. The
existing adapter-prefilter tests prove the intake filter lets the DM
through; this covers the downstream runner path the sweeper review flagged
as untested.
@PRATHAMESH75
PRATHAMESH75 force-pushed the fix/telegram-allow-all-false-not-configured branch from b8874b8 to 38285c3 Compare August 16, 2026 09:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/auth Authentication, OAuth, credential pools comp/plugins Plugin system and bundled plugins P3 Low — cosmetic, nice to have platform/telegram Telegram bot adapter sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(telegram): auth prefilter treats GATEWAY_ALLOW_ALL_USERS=false as configured, blocking DM pairing

4 participants