You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
PR #4341 codified the invariant: admin bypass (JWT teams=null + is_admin=true, or non-JWT dev-mode admin) must not grant visibility to another user's private resources. The fix was applied across the main service surfaces (tools, prompts, resources, servers, gateways, A2A agents, templates, tag and completion enumeration).
Two adjacent A2A call sites were flagged by Oracle during the #4341 review as not currently exposed via the routers (so they did not block the PR), but they still encode the old semantics at the service layer and are a footgun for future callers.
A2AAgentService.list_tasks: thread the task->agent join through _check_agent_access (or the equivalent query-level filter) so admin bypass stops returning tasks on private agents.
Add regression tests in tests/unit/mcpgateway/services/ that exercise each path with (user_email=None, token_teams=None) against private+team+public fixtures, modelled on TestDirectGetAccessDenial in tests/unit/mcpgateway/services/test_authorization_access.py.
Scope
Low risk: no live endpoint presently hits these paths with admin-bypass, so the fix is a defensive alignment, not an observable behavior change for current callers.
Security-adjacent: keeping this drift un-fixed is a latent source of bypass if a future router hooks into these helpers directly.
Context
PR #4341 codified the invariant: admin bypass (JWT
teams=null+is_admin=true, or non-JWT dev-mode admin) must not grant visibility to another user's private resources. The fix was applied across the main service surfaces (tools, prompts, resources, servers, gateways, A2A agents, templates, tag and completion enumeration).Two adjacent A2A call sites were flagged by Oracle during the #4341 review as not currently exposed via the routers (so they did not block the PR), but they still encode the old semantics at the service layer and are a footgun for future callers.
What's inconsistent
1.
a2a_server_service._check_server_accessmcpgateway/services/a2a_server_service.py:41-43Truewhenuser_email is None and token_teams is None, treating admin bypass as unrestricted — including private servers.Truefor public/team butFalsewhen the server'svisibility == "private".(None, None).2.
A2AAgentService.list_tasksmcpgateway/services/a2a_service.py:380-399(user_email=None, token_teams=None), returns all tasks including those on private agents — the original pre-fix(security): prevent admin bypass from accessing private resources #4341 "admin sees everything" behavior._check_agent_access).user_emailthrough rather than invoking the admin-bypass code path directly.Proposed fix
a2a_server_service._check_server_access: add the admin-bypass-denies-private branch (visibility != "private"), matching the pattern inserver_service._check_server_accessintroduced by fix(security): prevent admin bypass from accessing private resources #4341.A2AAgentService.list_tasks: thread the task->agent join through_check_agent_access(or the equivalent query-level filter) so admin bypass stops returning tasks on private agents.tests/unit/mcpgateway/services/that exercise each path with(user_email=None, token_teams=None)against private+team+public fixtures, modelled onTestDirectGetAccessDenialintests/unit/mcpgateway/services/test_authorization_access.py.Scope
References
AGENTS.md— "Authentication & RBAC Overview" and "Security Invariants"docs/docs/architecture/multitenancy.md— canonical visibility semantics