fix(gateway): stop multiplex second auth gate from leaking allowlists… - #80360
fix(gateway): stop multiplex second auth gate from leaking allowlists…#80360OWWZO wants to merge 2 commits into
Conversation
…NousResearch#80026) Route _is_user_authorized allowlist/allow-all reads through _platform_gate_env so a profile-scoped miss does not fall back to process-global os.environ under multiplex. Remove the redundant _auth_env helper and add Discord/QQ regression coverage.
|
suggesting changes A P1 profile-isolation gap remains: multiplexed busy-session and startup-resume authorization can run outside the routed profile secret scope. The shared busy-session callback is installed without a profile wrapper, and startup resume validates the session owner before entering the scoped handler. In those paths the authorization helper can read the process-global allowlist, so a value from one profile can authorize a busy-session action or resume a revoked session for another profile. Wrap each profile-bound authorization call in the routed profile scope, including the busy-session callback, startup-resume validation, and adapter authorization callback, and add regression coverage for foreign allowlists and revoked session owners. Security evidence:
Not checked:
Signed: GPT-5.6-luna-max in Codex |
Close residual P1 isolation gap: busy-session, startup-resume owner checks, and adapter auth callbacks ran outside the routed profile secret scope and could honor a foreign process allowlist. Wrap those paths and add regression coverage for foreign allowlists and revoked session owners.
Thanks for the residual-bypass report — agreed, that was a real P1 gap beyond the cold-path fix.
|
|
fully addressed The current head closes the cross-profile authorization gap from my earlier review. Busy-session and startup-resume checks now authorize inside the routed profile scope, secondary adapter callbacks bind their own profile, and multiplex allowlist/allow-all reads no longer inherit a foreign process-global value. On a clean replay onto current Not checked:
Signed: GPT-5.6-sol-xhigh in Codex |
|
suggesting changes The current head still leaves a cross-profile authorization bypass in multiplexed Telegram and Slack adapter paths. Their wrapper handlers are closures rather than runner-bound methods, so the callback and intake gates fall back to process-global allowlists when no profile scope is installed. A value from another profile can therefore authorize Telegram approval/confirmation/clarify controls, Telegram message intake, or Slack interactive controls. Bind these paths to the routed profile-scoped authorization callback and make multiplex fallbacks deny on a missing scope or resolver failure, while preserving profile-local P3 follow-up: profile-route rejection and profile-directory resolution errors can also fall back to unscoped authorization. Rejected routes should be dropped and resolver failures should fail closed for busy, resume, and adapter-context callers. Security evidence:
Not checked:
Signed: GPT-5.6-sol-xhigh in Codex |
|
Implemented on main via #93446 (2912c36). Your approach — routing the admission-gate reads ( |
… (#80026)
Route _is_user_authorized allowlist/allow-all reads through _platform_gate_env so a profile-scoped miss does not fall back to process-global os.environ under multiplex. Remove the redundant _auth_env helper and add Discord/QQ regression coverage.
What does this PR do?
Fixes the gateway's second authorization gate under
multiplex_profiles: aprofile-scoped miss no longer falls through to process-global
os.environ,so profile B cannot inherit profile A's bridged allowlist
(
DISCORD_ALLOWED_USERS,*_ALLOW_ALL_USERS,GATEWAY_*, etc.).Approach: route all
_is_user_authorizedallowlist/allow-all reads throughthe existing multiplex-authoritative
_platform_gate_env()and remove theredundant
_auth_env()helper (which fell back toos.getenvon a scopedmiss). Single-profile deployments keep legacy env behavior.
Related open PR #80238 fixes the same hole by inlining the isolation guard
into
_auth_env. This PR consolidates onto one reader and adds regressiontests (Discord + QQ). Happy to close in favor of #80238 if maintainers
prefer the smaller call-site-preserving diff — please keep the tests.
Related Issue
Fixes #80026
Also closes residual gateway-gate gap left after #75970 (adapter-level fix
for #72348). Broader transport/provenance work remains in #76166.
Type of Change
Changes Made
gateway/authz_mixin.py: remove_auth_env; use_platform_gate_envforplatform allow-all, platform/group allowlists,
GATEWAY_ALLOWED_USERS,and
GATEWAY_ALLOW_ALL_USERSin_is_user_authorizedtests/gateway/test_discord_multiplex_second_auth_gate.py: new regressionfor [Bug]: Discord multiplex gateway second auth gate can apply another profile’s allowlist after #75970 #80026 (foreign allowlist / allow-all must not authorize secondary;
scoped allowlist still works; single-profile env unchanged)
tests/gateway/test_qqbot_scope_paths.py: remove xfail ontest_scope_does_not_inherit_environ_opt_in; add empty-scope allowlistnon-inheritance case
How to Test
TestAuthzAllowAllScope::test_scope_does_not_inherit_environ_opt_in.
allowlists — profile A's user must be denied on profile B; profile B's
configured user must still authorize.
Observed locally (Windows, Python 3.11): 56 passed on the focused set above.
Checklist
Code
fix(scope):,feat(scope):, etc.)pytest tests/ -qand all tests passDocumentation & Housekeeping
docs/, docstrings) — or N/Acli-config.yaml.exampleif I added/changed config keys — or N/ACONTRIBUTING.mdorAGENTS.mdif I changed architecture or workflows — or N/AFor New Skills
hermes --toolsets skills -q "Use the X skill to do Y"Screenshots / Logs