fix(rbac): don't let namespaced roles grant cluster-scoped actions - #614
Merged
Conversation
dcharles525
marked this pull request as ready for review
July 23, 2026 21:48
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PR Checklist
epinio/docs#491
Summary
The dashboard showed Create/Edit/Delete buttons for cluster-scoped resources
(app charts, builder images, git configs, catalog services, namespace create)
to users who can't actually perform them. The clearest case is the default
epiniouser: itsadmin:workspacerole made the buttons appear, but theserver 403s the request.
Occurred changes and/or fixed issues
Root cause:
buildPermissionsFromRolesflattened every role from/api/v1/meinto one permission map, ignoring
role.namespace. A namespace-scoped admin(
admin:workspace) therefore granted cluster-scoped actions globally. The UInow gates cluster-scoped writes against global (non-namespaced) roles only,
matching the server's
User.IsAllowed. No server change.Technical notes summary
utils/permissions.ts: build aglobalActionsset (actions fromnamespace-less roles); override
CLUSTER_SCOPED_ACTIONS(
chart_write,builderimage_write,gitconfig_write) toglobalActions.has(a). Catalog and namespace are mixed actions (only part iscluster-scoped), so derive
catalog_service_writefrom globalservice_writeand
namespace_createfrom globalnamespace_write.list/catalogservices.vue: create/edit/delete gate now usescatalog_service_write(matches the detail view).list/namespaces.vue: split the create gate from delete; create uses globalnamespace_create, delete stays onnamespace_write(per-namespace).Areas or cases that should be tested
As default
epiniouser (userglobal +admin:workspace):userrole holdsbuilderimage_write).namespace_read;namespace Delete still shown for the admin'd namespace.
As a global admin: all Create buttons shown. As
view_only: none.Sanity check: a direct
POST /appchartsstill returns 403 (UI now matches theserver; server behavior is unchanged). Tested in ; reviewer please use
a different one.
Areas which could experience regressions
All permission-gated Create/Edit/Delete buttons, since they share the
epinio/cangetter. Most exposed: namespace delete (gate was split) and catalogmanagement (gate repointed). Server enforcement is unchanged, so the worst case
is a button shown/hidden mismatch, not an auth bypass. Global roles (admin,
application_manager, etc.) are unaffected, their actions are in
globalActions.