Why Kubernetes RBAC Is Almost Always Misconfigured
Cybersecurity
Most teams running Kubernetes have RBAC. Most of them have it wrong in ways that aren't obvious until you trace through it. The non-obvious misconfigurations look like a role that's correct but lets a service account read every secret in the cluster.
By Arjun Raghavan, Security & Systems Lead, BIPI · June 30, 2025 · 7 min read
Most teams that run Kubernetes have RBAC. Most of them have it wrong in ways that are not obvious until you trace through it. The CIS Kubernetes Benchmark catches the obvious bits. The non-obvious bits look like a Role that is correct in isolation but composes with a default ServiceAccount and a permissive ClusterRoleBinding to grant cluster-wide secret read.
We have audited enough production Kubernetes clusters to recognise the same five mistakes. Three are configuration. Two are architectural.
1. The default ServiceAccount problem
Every namespace gets a 'default' ServiceAccount. Every Pod that does not explicitly set serviceAccountName gets the default. That ServiceAccount used to mount a token automatically. Pre-1.24 clusters still have this on by default; 1.24+ requires automountServiceAccountToken: true to opt in.
The bug: teams add ClusterRoleBindings to 'default' for some debugging convenience, forget about it, and now every Pod in every namespace has those permissions automatically. We have found 'default' bound to view (cluster-wide) on 6 of the last 10 clusters we audited. View includes secret read.
2. Wildcards in roles
A Role or ClusterRole with verbs: ['*'] or resources: ['*'] is rarely what was intended. Wildcards land in roles for two reasons: a developer was trying to make something work and tightened it 'later'; a Helm chart shipped with broad permissions because the maintainer did not want to deal with edge cases. 'Later' rarely arrives.
The audit query is one kubectl invocation:
kubectl get clusterroles -o json | jq '.items[] | select(.rules[]? | (.verbs | contains(["*"])) or (.resources | contains(["*"]))) | .metadata.name'
3. Aggregated ClusterRoles that nobody audits
Kubernetes lets a ClusterRole be 'aggregated' — its rules come from any other ClusterRole that matches a label selector. The 'admin' ClusterRole, for example, aggregates rules labelled rbac.authorization.k8s.io/aggregate-to-admin: "true".
When an operator (Cert Manager, Argo CD, Crossplane, etc.) installs and adds an aggregating ClusterRole, that role's rules silently become part of admin without any explicit binding. The cluster admin sees admin's permissions grow over time without any direct change to admin itself. Every install adds to the surface.
4. Namespace boundaries are not security boundaries
RBAC scopes by namespace. The Kubernetes API trusts the namespace boundary as a logical separation. The kernel does not. A compromised container can break out via a kernel CVE, escape the runtime, and then namespace-level RBAC is irrelevant — the attacker is on the node.
Teams that treat namespaces as security boundaries (e.g., 'tenant-a' and 'tenant-b' in the same cluster, separated by RBAC) are running multi-tenant on shared kernels. That is a Pod Security Standards problem and a runtime-isolation problem, not an RBAC problem. RBAC is not enough.
5. Stale tokens and orphaned ServiceAccounts
Every ServiceAccount has a long-lived token (pre-1.24) or projected token (post-1.24). Teams create ServiceAccounts for batch jobs and forget to delete them. The bound ClusterRole stays. The token stays. Six months later it is still valid and still privileged.
Audit: list every ServiceAccount, find the ones with no Pod referencing them, with no recent token usage in audit logs. Delete the orphans. Repeat quarterly.
What right-sized RBAC looks like
- Every Pod has automountServiceAccountToken: false unless it specifically calls the Kubernetes API.
- Every ServiceAccount that does call the API has a custom Role with explicit verbs and resources. No wildcards.
- ClusterRoles aggregated by operators are reviewed quarterly. New operators get a one-page review of what they aggregate before install.
- RBAC is one of three layers. Pod Security Standards (Restricted profile) is the second. Network policies are the third.
- Audit logs ship to your SIEM. Watchdog rules flag any new ClusterRoleBinding to 'cluster-admin' or any binding to the 'default' ServiceAccount.
Closing
Kubernetes RBAC is precise but the precision is in fragments — Roles, RoleBindings, ClusterRoles, aggregated ClusterRoles, ServiceAccount tokens, default service accounts. Each fragment can be correct while the composition is permissive. The audit is in the composition. Run the queries quarterly and the cluster stays defensible.
Read more field notes, explore our services, or get in touch at info@bipi.in. Privacy Policy · Terms.