62%
of Kubernetes clusters have overprivileged service accounts per Aqua Security research
94
distinct Kubernetes attack techniques documented in MITRE ATT&CK for Containers
3x
higher breach likelihood for clusters with cluster-admin bindings on default service accounts

Kubernetes RBAC (Role-Based Access Control) is the gatekeeper for everything in your cluster: who can read secrets, who can exec into pods, who can create new workloads. When it is misconfigured, attackers who compromise one pod can pivot to own your entire infrastructure. This guide covers how to design RBAC correctly from the start, how to audit existing permissions, and the specific misconfigurations that show up in nearly every real-world cluster compromise.

How Kubernetes RBAC Works

Kubernetes RBAC operates on four core resources:

  • Role -- defines allowed verbs (get, list, create, delete, patch, watch, *) on specific API resources within a namespace
  • ClusterRole -- same as Role but cluster-scoped (applies across all namespaces, or to non-namespaced resources)
  • RoleBinding -- binds a Role or ClusterRole to a subject (user, group, or ServiceAccount) within a namespace
  • ClusterRoleBinding -- binds a ClusterRole to a subject cluster-wide

The evaluation engine is additive: there are no deny rules. A principal has a permission if any binding grants it. This means the attack surface grows with every role and binding you create.

Subjects in RBAC:

Subject TypeTypical UseRisk Level
UserHuman operators (via OIDC/cert)Medium -- humans make mistakes
GroupTeams bound to IdP groupsMedium -- group sprawl is common
ServiceAccountWorkload identity for podsHigh -- often over-privileged

The RBAC API uses these verbs against these resource groups most commonly exploited:

verbs: ["get", "list", "watch"]          # read-only -- relatively safe
verbs: ["create", "update", "patch"]     # write -- dangerous on secrets/configmaps
verbs: ["delete"]                        # destructive -- high impact
verbs: ["*"]                             # wildcard -- almost never justified
resources: ["secrets"]                   # contains credentials, tokens
resources: ["pods/exec"]                 # RCE inside the cluster
resources: ["pods/portforward"]          # lateral movement
resources: ["clusterrolebindings"]       # privilege escalation

The authentication flow: Kubernetes authenticates requests via certificates, bearer tokens (ServiceAccount JWT or OIDC), or webhook authenticators. RBAC authorization then evaluates whether the authenticated identity holds a binding that permits the requested verb+resource combination.

Least-Privilege Role Design Principles

The default posture in most clusters is over-permissive. Here is how to design roles that actually enforce least privilege.

Principle 1: Namespace isolation as a blast radius limiter

Use namespaces to segment workloads by trust level. Bind roles with RoleBinding (namespace-scoped) rather than ClusterRoleBinding wherever possible. A compromised pod in the payments namespace with a RoleBinding cannot affect the infra namespace.

Principle 2: Avoid binding ClusterRoles cluster-wide

The view, edit, and admin ClusterRoles are convenient but dangerous when bound cluster-wide. A ClusterRoleBinding for view on a developer account means they can list secrets in every namespace -- including those containing cloud provider credentials. Use namespace-scoped RoleBindings even when referencing ClusterRoles.

Principle 3: Never use cluster-admin except for break-glass accounts

cluster-admin is equivalent to root on the entire cluster. Audit all ClusterRoleBindings referencing it:

kubectl get clusterrolebindings -o json | \
  jq '.items[] | select(.roleRef.name=="cluster-admin") | {name: .metadata.name, subjects: .subjects}'

Any result should be treated as a high finding unless it is an explicitly approved break-glass account with MFA enforcement on the underlying identity.

Principle 4: Grant specific verbs, not wildcards

Instead of:

rules:
  - apiGroups: [""]
    resources: ["*"]
    verbs: ["*"]

Write:

rules:
  - apiGroups: ["apps"]
    resources: ["deployments"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "list"]

Principle 5: Use resourceNames for surgical access

Restrict access to specific named resources where possible:

rules:
  - apiGroups: [""]
    resources: ["configmaps"]
    resourceNames: ["app-config"]
    verbs: ["get"]

This prevents a workload from reading all ConfigMaps in the namespace.

Free daily briefing

Briefings like this, every morning before 9am.

Threat intel, active CVEs, and campaign alerts, distilled for practitioners. 50,000+ subscribers. No noise.

Service Account Hardening

Service accounts are the most common RBAC vulnerability in production clusters. By default, Kubernetes:

  1. Auto-creates a default service account in every namespace
  2. Auto-mounts the service account token into every pod
  3. Grants the default service account no RBAC permissions -- but CI/CD pipelines and operators frequently add permissions to it without realizing the blast radius

Critical hardening steps:

Disable auto-mounting by default:

At the namespace level (patch the default service account):

apiVersion: v1
kind: ServiceAccount
metadata:
  name: default
  namespace: your-namespace
automountServiceAccountToken: false

On individual pods:

spec:
  automountServiceAccountToken: false

Create dedicated service accounts per workload:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: payment-processor
  namespace: payments
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::123456789:role/payment-processor  # IRSA on EKS
---
apiVersion: apps/v1
kind: Deployment
spec:
  template:
    spec:
      serviceAccountName: payment-processor
      automountServiceAccountToken: true  # only true because this SA needs API access

Use projected service account tokens (Kubernetes 1.20+):

Projected tokens are time-limited and audience-bound -- they cannot be replayed against other services:

volumes:
  - name: token
    projected:
      sources:
        - serviceAccountToken:
            audience: "my-service"
            expirationSeconds: 3600
            path: token

Audit service account token usage with audit logs:

Look for ServiceAccount tokens being used from outside the cluster (sourceIPs not in your pod CIDR range) -- a sign of token theft.

Common RBAC Misconfigurations Attackers Exploit

Real-world cluster compromises follow predictable RBAC patterns.

Misconfiguration 1: pods/exec granted to broad subjects

pods/exec is effectively remote code execution. Any role with this permission can run arbitrary commands in any pod in scope. Check:

kubectl get roles,clusterroles -A -o json | \
  jq '.items[] | select(.rules[]?.resources[]? == "pods/exec") | .metadata.name'

Misconfiguration 2: secrets list/get granted to workloads

Workloads almost never need to list or get Kubernetes Secrets -- they should receive secrets via environment variables or projected volumes. A workload with secrets get can read every credential in its namespace.

Misconfiguration 3: Privilege escalation via rolebindings create

A principal with permission to create RoleBindings in a namespace can grant themselves any permission that exists in that namespace -- even permissions they do not hold. This is a privilege escalation path analogous to PassRole in AWS IAM:

# Attacker with rolebindings create in namespace "app" can do:
kubectl create rolebinding attacker-admin --clusterrole=admin --serviceaccount=app:attacker-sa -n app

Misconfiguration 4: Helm RBAC (Tiller legacy)

Older Helm v2 installations ran Tiller with cluster-admin. While Helm v3 eliminated Tiller, many clusters still have tiller service accounts with broad ClusterRoleBindings from legacy installations.

Misconfiguration 5: Operator CRD over-permissioning

Kubernetes operators frequently request broad RBAC permissions during installation. Audit the RBAC manifests in every operator Helm chart before deployment. Common culprits include monitoring operators that request cluster-wide secrets access.

Detection query (audit log):

Watch for these audit log patterns in your SIEM:

EventMeaning
verb=create, resource=clusterrolebindingsPrivilege escalation attempt
verb=get, resource=secrets, user=system:serviceaccountSA reading secrets directly
verb=create, resource=pods, subresource=execInteractive shell in pod
verb=list, resource=pods, namespace=kube-systemReconnaissance of control plane

Auditing Existing RBAC with kubectl and Open Source Tools

Most clusters accumulate RBAC debt over time. These tools help you find it.

kubectl-who-can:

Shows which subjects can perform a specific action:

kubectl who-can get secrets -n production
kubectl who-can create clusterrolebindings
kubectl who-can exec pods

Install via Krew: kubectl krew install who-can

rbac-tool:

Generates a visual graph of all subjects, roles, and bindings:

kubectl rbac-tool lookup system:serviceaccount:kube-system:default
kubectl rbac-tool policy-rules -e '^system'  # exclude system accounts

rakkess (access matrix):

Prints which verbs a service account can perform on all resources -- useful for quickly spotting over-permissioned accounts:

rakkess --sa kube-system:default

Automated audit checklist:

# 1. Find all cluster-admin bindings
kubectl get clusterrolebindings -o json | jq '.items[] | select(.roleRef.name=="cluster-admin")'

# 2. Find service accounts with wildcard verbs
kubectl get roles,clusterroles -A -o json | jq '.items[] | select(.rules[]?.verbs[]? == "*")'

# 3. Find pods with automounted tokens that have API access
kubectl get pods -A -o json | jq '.items[] | select(.spec.automountServiceAccountToken != false)'

# 4. List all role bindings across all namespaces
kubectl get rolebindings -A -o wide

Run this audit quarterly and after every major operator or tooling installation.

Enabling and Using Kubernetes Audit Logs for RBAC Monitoring

Kubernetes audit logs record every API server request with full context: who, what, when, and the result. Without them, you have no visibility into RBAC abuse.

Audit policy configuration:

Create an audit policy at /etc/kubernetes/audit-policy.yaml on your control plane:

apiVersion: audit.k8s.io/v1
kind: Policy
rules:
  # Log all requests to secrets at RequestResponse level
  - level: RequestResponse
    resources:
      - group: ""
        resources: ["secrets"]

  # Log exec, portforward at Metadata level
  - level: Metadata
    resources:
      - group: ""
        resources: ["pods/exec", "pods/portforward", "pods/attach"]

  # Log RBAC changes at RequestResponse
  - level: RequestResponse
    resources:
      - group: "rbac.authorization.k8s.io"
        resources: ["clusterroles", "clusterrolebindings", "roles", "rolebindings"]

  # Omit high-volume, low-value events
  - level: None
    users: ["system:kube-proxy"]
    verbs: ["watch"]
    resources:
      - group: ""
        resources: ["endpoints", "services", "services/status"]

  # Default: Metadata for everything else
  - level: Metadata

SIEM correlation rules for RBAC abuse:

Forward audit logs to your SIEM and build alerts for:

AlertCondition
Privilege escalationverb=create AND resource=clusterrolebindings
Secret enumerationverb=list AND resource=secrets AND user != system:serviceaccount:kube-system:*
Shell in podverb=create AND resource=pods AND subresource=exec
Role with wildcardverb=create AND resource=clusterroles AND requestObject contains verbs=[*]
Anonymous accessuser=system:anonymous

The bottom line

Kubernetes RBAC is not a one-time setup -- it is an ongoing hygiene practice. Start with a least-privilege audit using kubectl-who-can and rakkess, disable auto-mounting on every service account that does not need API access, remove all wildcard verbs, and wire audit logs to your SIEM. The clusters that get compromised are not the ones that enabled RBAC; they are the ones that enabled it and then stopped paying attention.

Frequently asked questions

What is the difference between a Role and a ClusterRole in Kubernetes?

A Role is namespace-scoped: it only grants permissions within the namespace where it is created. A ClusterRole is cluster-scoped: it can grant permissions on non-namespaced resources (like nodes and persistent volumes) or be reused across namespaces via RoleBindings. The key operational rule is to prefer namespace-scoped RoleBindings even when referencing ClusterRoles -- this limits the blast radius of a compromised account to a single namespace.

How do I find overprivileged service accounts in my cluster?

Use three tools in combination: kubectl-who-can (shows who can do a specific action), rakkess (generates an access matrix for a service account), and a direct audit of ClusterRoleBindings referencing cluster-admin. Run: `kubectl get clusterrolebindings -o json | jq '.items[] | select(.roleRef.name=="cluster-admin")'` to immediately see your highest-risk bindings. Also check for roles with wildcard verbs: `kubectl get roles,clusterroles -A -o json | jq '.items[] | select(.rules[]?.verbs[]? == "*")'`.

Is it safe to disable automountServiceAccountToken on all pods?

It is safe to disable on any pod that does not make direct Kubernetes API calls. The vast majority of application workloads (web servers, databases, message consumers) do not need to call the Kubernetes API, so their service account token mount is pure attack surface. Disable it by default at the ServiceAccount level and re-enable only for workloads that explicitly need API access (operators, monitoring agents, CI/CD runners). Set automountServiceAccountToken: false on the default service account in every namespace.

What are the most dangerous Kubernetes RBAC permissions to grant?

In order of severity: (1) cluster-admin ClusterRoleBinding -- full cluster control; (2) clusterrolebindings create/update -- allows self-escalation to any role; (3) pods/exec -- interactive shell in any pod; (4) secrets get/list -- credential access; (5) nodes/proxy -- can proxy traffic through the kubelet to access pod APIs without going through the API server. Treat these as critical findings in any RBAC audit.

How should I handle RBAC for CI/CD pipelines?

Create a dedicated service account for each pipeline with the minimum permissions needed for deployment. For a typical deployment pipeline, this means: `deployments update/patch` in specific namespaces, `configmaps get/list` if config is read at deploy time, and `secrets get` only for the specific secrets needed. Never grant pipelines cluster-admin or the ability to create ClusterRoleBindings. Use IRSA (EKS), Workload Identity (GKE), or Pod Identity (AKS) to bind the service account to a cloud IAM role for cloud resource access, avoiding long-lived static credentials.

Do Kubernetes network policies replace the need for RBAC hardening?

No -- they are complementary controls at different layers. Network policies control pod-to-pod and pod-to-service traffic (layer 3/4). RBAC controls who can interact with the Kubernetes API (create pods, read secrets, exec into containers). An attacker who compromises a pod can still call the Kubernetes API using the auto-mounted service account token even if network policies block direct pod-to-pod communication. Both controls are required: network policies for lateral movement containment, RBAC for privilege escalation prevention.

Sources & references

  1. Kubernetes RBAC Documentation
  2. NSA/CISA Kubernetes Hardening Guide
  3. MITRE ATT&CK for Containers
  4. Aqua Security State of Cloud Security Report 2024

Free resources

25
Free download

Critical CVE Reference Card 2025–2026

25 actively exploited vulnerabilities with CVSS scores, exploit status, and patch availability. Print it, pin it, share it with your SOC team.

No spam. Unsubscribe anytime.

Free download

Ransomware Incident Response Playbook

Step-by-step 24-hour IR checklist covering detection, containment, eradication, and recovery. Built for SOC teams, IR leads, and CISOs.

No spam. Unsubscribe anytime.

Free newsletter

Get threat intel before your inbox does.

50,000+ security professionals read Decryption Digest for early warnings on zero-days, ransomware, and nation-state campaigns. Free, weekly, no spam.

Unsubscribe anytime. We never sell your data.

Eric Bang
Author

Founder & Cybersecurity Evangelist, Decryption Digest

Cybersecurity professional with expertise in threat intelligence, vulnerability research, and enterprise security. Covers zero-days, ransomware, and nation-state operations for 50,000+ security professionals weekly.

Free Brief

The Mythos Brief is free.

AI that finds 27-year-old zero-days. What it means for your security program.

Joins Decryption Digest. Unsubscribe anytime.

Daily Briefing

Get briefings like this every morning

Actionable threat intelligence for working practitioners. Free. No spam. Trusted by 50,000+ SOC analysts, CISOs, and security engineers.

Unsubscribe anytime.

Mythos Brief

Anthropic's AI finds zero-days your scanners miss.