Skip to content

test(telegram): pin comma-string allow_from / group_allow_from in adapter auth - #63350

Open
Rival wants to merge 1 commit into
NousResearch:mainfrom
Rival:fix/allow-from
Open

test(telegram): pin comma-string allow_from / group_allow_from in adapter auth#63350
Rival wants to merge 1 commit into
NousResearch:mainfrom
Rival:fix/allow-from

Conversation

@Rival

@Rival Rival commented Jul 12, 2026

Copy link
Copy Markdown

Rebased onto current main — scope reduced to tests only. See the rebase note in the comments: main fixed the underlying parsing bug independently via the _coerce_allow_set extraction, so this PR's original one-line production change is now redundant and has been dropped. What remains is the regression coverage, which main does not have.

What

Three tests in tests/gateway/test_telegram_auth_check.py pinning that a comma-string allow_from / group_allow_from behaves exactly like the equivalent YAML list in TelegramAdapter._is_user_authorized_from_message.

No production change.

Why

_is_user_authorized_from_message picks group_allow_from for group/forum/channel and allow_from for DMs, then parses whichever it chose with _coerce_allow_set. Both keys accept either form:

  • a list allow_from is ",".join(...)-ed onto TELEGRAM_ALLOWED_USERS, and the env branch of this same method splits it;
  • scalar YAML — allow_from: "111,222" — reaches the adapter as one string.

If such a value were ever iterated directly instead of split, the allow-set would become single characters: every real user id rejected, locking the owner out of their own bot. That is a lockout-class failure, and it is the failure this branch originally shipped a fix for.

_coerce_allow_set handles it correctly today. But the existing adapter-auth tests (..._allow_from, ..._group_allow_from) exercise the list form only — nothing pins the string form through either branch, so the behavior could regress silently.

Ships

  • ..._comma_string_allow_from — comma-string via allow_from on a DM.
  • ..._comma_string_group_allow_from — comma-string via group_allow_from in a group.
  • ..._comma_string_with_spaces" 111 , 222 " tolerated (same .strip() as the env branch).
  • ..._comma_string_wildcard — a bare * scalar still wildcards.

Verified adversarially: reverting _coerce_allow_set to the pre-extraction {str(u).strip() for u in raw} comprehension makes three of these four fail. (The wildcard case passes either way — iterating "*" char-wise still yields {"*"} — so it is coverage, not a discriminator.)

@alt-glitch alt-glitch added type/bug Something isn't working comp/gateway Gateway runner, session dispatch, delivery platform/telegram Telegram bot adapter area/auth Authentication, OAuth, credential pools P2 Medium — degraded but workaround exists sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data labels Jul 12, 2026
@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 16, 2026
@Rival Rival changed the title fix(telegram): accept comma-string allow_from in adapter auth check test(telegram): pin comma-string allow_from / group_allow_from in adapter auth Jul 29, 2026
@Rival

Rival commented Jul 29, 2026

Copy link
Copy Markdown
Author

Rebased onto current main, and the rebase turned up something worth flagging: main has already fixed this bug independently, by a different route.

When this branch was cut, the adapter-level branch built its allow-set inline:

allowed = {str(u).strip() for u in adapter_allow_from if str(u).strip()}

Iterating a comma-string char-wise there is the lockout bug. main has since extracted that into gateway/authz_mixin.py::_coerce_allow_set, which splits a scalar on commas — its docstring even cites this exact case. So the one-line production change this PR shipped is now redundant, and I have dropped it rather than leave a no-op hunk in the diff for a reviewer to puzzle over.

Two other things the rebase surfaced:

  1. main also made allow_from DM-only, introducing group_allow_from for group/forum/channel. The original tests here set allow_from and used the _make_message default chat_type="group", so on current main they exercised neither branch and passed vacuously. They now pass explicit chat types, matching the style of the adjacent ..._allow_from / ..._group_allow_from tests.
  2. Neither of those adjacent tests covers the string form of either key — only lists. That gap is what is left worth merging, so this is now a tests-only PR (retitled accordingly).

Verified adversarially: reverting _coerce_allow_set to the old comprehension fails three of the four added tests. The wildcard case passes either way ("*" iterated char-wise is still {"*"}), so it is coverage rather than a discriminator — noting that explicitly rather than claiming four independent guards.

Happy to close this instead if you would rather not carry the extra coverage.

@GottZ

GottZ commented Aug 3, 2026

Copy link
Copy Markdown

This was generated by AI during triage.

Summary

Thirteen PRs address or reference three connected Telegram authorization problems: the original missing user/group controls, intake short-circuits that mask YAML or environment grants, and scalar parsing plus preservation of the documented global/group/chat authorization union. The diffs include the merged gateway implementation in #17748, overlapping group/DM fixes in #55496 and #55529, focused scalar regressions in #63350 and #64473, and broader union work culminating in #72084.

Related pull requests

Duplicates

#7659 and #17686 are predecessors of merged #17748; #55624 and #57189 duplicate the group-side work contained in #55496/#55529, with #55529 adding the complementary DM path. #63350 overlaps #64473 on CSV scalar coverage, while #68784 and #69617 are superseded approaches to the union problem carried forward more comprehensively by #72084.

Suggested consolidation

Keep #55529 open with a salvage path: preserve its combined group/DM fix, repair the explicit-empty fail-closed case identified on #55496, and add the alias and precedence documentation required by its maintainer-bot review. Close #55496 as duplicate of #55529 despite the keep_open review on #55496, because #55529's visible diff contains the same group/forum ordering and alias changes plus the missing DM fallback, while retaining the review's empty-list requirement for the consolidated patch; keep #63350 open for its focused regression tests, require author action on #64473 to preserve tuple/set iterable normalization, and require author action on recorded best fix #72084 to rebase onto main or split out the current intake/runner union and multiplex profile-scope work.

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
    subgraph Dup63350 ["PRs duplicating each other"]
        P63350["PR #63350 (open)"]
        P64473["PR #64473 (open)"]
    end
    class P63350 open
    class P64473 open
    class P63350 target
    click P63350 "https://github.com/NousResearch/hermes-agent/pull/63350"
    click P64473 "https://github.com/NousResearch/hermes-agent/pull/64473"
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 13 pull requests and 3 issues in this complex. Each diff was read against this issue; Assessment working set: 189 kB of PR diffs, 30 kB of issue/PR text, 25 kB of discussion (42 comments), 16 verify verdicts. verdicts reflect diff content, not PR titles. Part of an automated triage batch.

…pter auth

``_coerce_allow_set`` splits a scalar string on commas so
``allow_from: "111,222"`` yields {"111", "222"} rather than a set of single
characters. Nothing pinned that through the Telegram adapter's DM and group
branches — the existing coverage passes list forms only, so a regression to
char-wise iteration would lock every real id out (and admit stray one-char
matches) without failing a test.

Four cases: comma-string allow_from on the DM branch, comma-string
group_allow_from on the group branch (the two keys are selected by chat type
but parsed identically), surrounding whitespace, and a bare "*" scalar
wildcard.

Tests only — no production change.
@Rival

Rival commented Aug 7, 2026

Copy link
Copy Markdown
Author

Rebased onto main (87fd0ed25). main restructured this test file substantially — 6b81590c5 pruned most of the _is_user_authorized_from_message family (_wildcard, _no_from_user, _callback) plus test_unknown_dm_with_no_allowlist_passes_to_pairing, leaving test_is_user_authorized_from_message_allow_from as the only survivor.

The textual conflict would have re-added those. Rather than resolve it hunk by hunk, I rebuilt the commit on top of the current file so it adds only the four comma-string cases, immediately after the surviving list-form test:

  • allow_from comma-string through the DM branch
  • group_allow_from comma-string through the group branch
  • surrounding whitespace
  • bare "*" scalar wildcard

Diff is now +56/-0 — purely additive, no lines of yours touched.

Negative-checked: making _coerce_allow_set iterate a scalar char-wise fails the first three (the wildcard case correctly survives — a single "*" character iterated char-wise is still {"*"}, so it guards a different property). Full file green at 15 passed.

Still tests-only, as described in the earlier comment — the production fix this PR originally carried became a no-op once _coerce_allow_set was extracted, and remains dropped.

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/gateway Gateway runner, session dispatch, delivery P2 Medium — degraded but workaround exists 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.

4 participants