From 00857b184015578f6e0bb151b8fcf665b2c949bb Mon Sep 17 00:00:00 2001 From: Ryan Malloy Date: Sat, 27 Dec 2025 08:10:01 -0700 Subject: [PATCH] fix: enforce strict RBAC - deny access for users without groups Security fix: Previously users with no OAuth groups or unrecognized groups would default to READ_ONLY access. Now: - Empty groups = no permissions (denied access to all tools) - Unrecognized groups = no permissions (denied access) Also adds missing restart_service mapping to FULL_ADMIN permission. --- src/mcvsphere/permissions.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/mcvsphere/permissions.py b/src/mcvsphere/permissions.py index 1fda649..26efbe2 100644 --- a/src/mcvsphere/permissions.py +++ b/src/mcvsphere/permissions.py @@ -120,10 +120,11 @@ TOOL_PERMISSIONS: dict[str, PermissionLevel] = { "configure_ntp": PermissionLevel.HOST_ADMIN, "set_service_policy": PermissionLevel.HOST_ADMIN, # ═══════════════════════════════════════════════════════════════════════ - # FULL_ADMIN - Everything including guest OS and service control (10 tools) + # FULL_ADMIN - Everything including guest OS and service control (11 tools) # ═══════════════════════════════════════════════════════════════════════ "start_service": PermissionLevel.FULL_ADMIN, "stop_service": PermissionLevel.FULL_ADMIN, + "restart_service": PermissionLevel.FULL_ADMIN, # Guest OS operations (requires guest credentials, high privilege) "run_command_in_guest": PermissionLevel.FULL_ADMIN, "list_guest_processes": PermissionLevel.FULL_ADMIN, @@ -191,9 +192,10 @@ def get_user_permissions(groups: list[str] | None) -> set[PermissionLevel]: Returns: Set of granted permission levels (union of all group permissions). + Returns empty set if no recognized groups (deny all access). """ if not groups: - return {PermissionLevel.READ_ONLY} + return set() # No groups = no permissions (enforces RBAC) permissions: set[PermissionLevel] = set() @@ -201,10 +203,7 @@ def get_user_permissions(groups: list[str] | None) -> set[PermissionLevel]: if group in GROUP_PERMISSIONS: permissions.update(GROUP_PERMISSIONS[group]) - # Default to read-only if no recognized groups - if not permissions: - permissions.add(PermissionLevel.READ_ONLY) - + # No fallback - unrecognized groups get no permissions return permissions