-
Notifications
You must be signed in to change notification settings - Fork 615
[FEATURE]: Narrow RBAC Layer 2 permission checks to match session-token team scope #3799
Description
Context
PR #3217 adds session-token team narrowing at Layer 1 (visibility / token scoping). When a session token carries a JWT teams claim, resolve_session_teams() narrows the visible scope to the intersection of DB teams and JWT teams.
However, Layer 2 (RBAC / permission checks) is not narrowed to match. When team_id cannot be derived from the request context, PermissionService.check_permission() is called with check_any_team=True, which aggregates permissions from all of the user's team-scoped roles — not just the ones matching the narrowed token_teams.
Problem
A session token narrowed to team A for visibility can still satisfy RBAC checks using roles the user holds in team B.
Example:
- User has
developerrole in team A (tools.read, tools.execute) - User has
team_adminrole in team B (teams.*, tools.create, etc.) - User creates a session narrowed to team A via JWT
teams: ["A"] - Layer 1: correctly scoped to team A resources only
- Layer 2:
check_any_team=Trueaggregates roles from both A and B - Result: user gains
teams.*permissions from team B despite narrowing to team A
Affected Code
mcpgateway/middleware/rbac.py:563— setscheck_any_team=Truefor session tokens withoutteam_idmcpgateway/services/permission_service.py:134—get_user_permissions(..., include_all_teams=check_any_team)does not filter bytoken_teamsmcpgateway/services/permission_service.py:483— includes ALL team-scoped roles wheninclude_all_teams=True
Proposed Fix
When check_any_team=True and token_teams is a non-empty list (narrowed session), filter the team-scoped roles in get_user_permissions() to only include roles from teams in token_teams. This preserves existing behavior for un-narrowed sessions (where token_teams covers full DB membership) while correctly restricting narrowed sessions.
Note
This is a pre-existing behavior in the two-layer model, not introduced by #3217. The PR makes it more visible by advertising session-token narrowing that only applies to Layer 1. This issue tracks closing the gap in Layer 2.