From fb441dfae58f3e2241b0982246d81f59c649d0b0 Mon Sep 17 00:00:00 2001 From: Michael Suchacz <203725896+ibetitsmike@users.noreply.github.com> Date: Sun, 27 Sep 2026 06:25:05 +0000 Subject: [PATCH] fix(enterprise/coderd): reject case variants of built-in role names Custom role names are stored lowercase, so a custom role named Agents-Access became an agents-access role that the built-in role shadowed and that could not be deleted. --- enterprise/coderd/roles.go | 5 +++-- enterprise/coderd/roles_test.go | 10 ++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/enterprise/coderd/roles.go b/enterprise/coderd/roles.go index 318138c0b9..d33b4dd489 100644 --- a/enterprise/coderd/roles.go +++ b/enterprise/coderd/roles.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "net/http" + "strings" "github.com/go-chi/chi/v5" "github.com/google/uuid" @@ -291,8 +292,8 @@ func sdkPermissionToDB(p codersdk.Permission) database.CustomRolePermission { func validOrganizationRoleRequest(ctx context.Context, req codersdk.CustomRoleRequest, rw http.ResponseWriter) bool { // This check is not ideal, but we cannot enforce a unique role name in the db against - // the built-in role names. - if rbac.ReservedRoleName(req.Name) { + // the built-in role names. Custom role names are stored lowercase. + if rbac.ReservedRoleName(strings.ToLower(req.Name)) { httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ Message: "Reserved role name", Detail: fmt.Sprintf("%q is a reserved role name, and not allowed to be used", req.Name), diff --git a/enterprise/coderd/roles_test.go b/enterprise/coderd/roles_test.go index 63772d76c3..b2c44658ef 100644 --- a/enterprise/coderd/roles_test.go +++ b/enterprise/coderd/roles_test.go @@ -225,6 +225,16 @@ func TestCustomOrganizationRole(t *testing.T) { OrganizationID: first.OrganizationID.String(), }) require.ErrorContains(t, err, "Reserved") + + // Custom role names are stored lowercase, so a case variant would + // shadow the built-in role. + //nolint:gocritic // owner is required for this + _, err = owner.CreateOrganizationRole(ctx, codersdk.Role{ + Name: "Agents-Access", + DisplayName: "Testing Purposes", + OrganizationID: first.OrganizationID.String(), + }) + require.ErrorContains(t, err, "Reserved") }) // Attempt to add site & user permissions, which is not allowed