Back to Blog

Preventing RBAC Privilege Escalation for the CKS Exam: the escalate, bind & impersonate Verbs

A CKS-focused guide to RBAC privilege escalation — how the RBAC authorizer's escalation-prevention rule works, the escalate, bind and impersonate verbs that bypass it, the meta-permissions that let a subject grant itself more, and the auth can-i workflow to detect it all.

By Sailor Team , September 15, 2026

Most people learn RBAC as a way to grant access: write a Role, bind it to a ServiceAccount, done. On the Certified Kubernetes Security Specialist (CKS) exam, the harder — and more frequently tested — question is the inverse: which permissions let a subject grant itself more permissions? That is privilege escalation, and RBAC has three special verbs that exist precisely to control it: escalate, bind, and impersonate.

If you already know how to create a least-privilege Role, this guide is the next layer. We assume the fundamentals from the CKS cluster setup and hardening guide — Role vs ClusterRole, RoleBinding vs ClusterRoleBinding, and the kubectl auth can-i habit — and focus entirely on the escalation mechanics that the exam’s “minimize exposure with RBAC” objective is really testing.

Why RBAC Is an Escalation Surface

RBAC is additive and permissive-by-omission: a subject can do exactly what some binding grants, and nothing else. That sounds safe until you notice that some permissions are permissions to manage permissions. If a compromised ServiceAccount can create a ClusterRoleBinding, it can bind itself to cluster-admin and own the cluster. The blast radius of a leaked token isn’t the token’s current rights — it’s the transitive closure of everything those rights can be used to grant.

The exam rewards you for spotting these transitive paths in a Role and shutting them down. There are three categories to internalize:

Escalation pathWhat it looks like in a RoleWhy it’s dangerous
Manage RBAC objectscreate/update/patch on roles, rolebindings, clusterroles, clusterrolebindingsWrite your own grants
Special verbsescalate, bind, impersonateBypass the built-in guardrails
Control a powerful identitycreate pods, create on serviceaccounts/token, control a Secret holding a tokenBorrow someone else’s rights

Kubernetes anticipated the first category, so it built two guardrails into the RBAC authorizer. Understanding those guardrails — and the verbs that turn them off — is the core of this topic.

Guardrail #1: Escalation Prevention and the escalate Verb

Here is the rule most candidates miss: you cannot create or update a Role or ClusterRole that contains permissions you do not already hold. The RBAC authorizer checks every rule in the role you are trying to write against your own effective permissions. If any rule grants something you can’t already do, the request is rejected — even if you have create on roles.

This stops the obvious attack. A user with create rolebindings and create roles in a namespace cannot simply author a Role with verbs: ["*"] on secrets and grant it to themselves, because they don’t already hold * on secrets.

The escalate verb is the deliberate exception. Granting escalate on roles/clusterroles turns the check off for that subject, letting them write roles more powerful than their own:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: role-author-danger
rules:
  # With this, the subject can craft ANY ClusterRole, including cluster-admin-equivalent
  - apiGroups: ["rbac.authorization.k8s.io"]
    resources: ["clusterroles"]
    verbs: ["create", "update", "escalate"]

On the exam, if you see escalate in a rule, treat it as a red flag and be ready to explain why: it removes the guardrail that would otherwise confine a role author to their own privilege level. Legitimate uses exist (controllers that manage roles), but for a hardening task, escalate almost never belongs on a workload ServiceAccount.

Guardrail #2: Binding Restrictions and the bind Verb

The second guardrail governs binding, not authoring. To create a RoleBinding or ClusterRoleBinding that references a role, you must satisfy one of two conditions:

  1. You already hold all the permissions contained in the role you’re referencing, or
  2. You have the bind verb on that specific role.

Without this, a subject with create rolebindings could bind the built-in cluster-admin ClusterRole to themselves. The guardrail blocks that: since they don’t already have cluster-admin, and they don’t have bind on cluster-admin, the binding is refused.

The bind verb is how you grant a controlled exception. Note that it is usually scoped to named roles with resourceNames, so a subject can bind only an approved role and nothing more powerful:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: can-bind-view-only
rules:
  - apiGroups: ["rbac.authorization.k8s.io"]
    resources: ["clusterroles"]
    verbs: ["bind"]
    resourceNames: ["view"]   # may ONLY bind the built-in 'view' ClusterRole

Exam reflex: create on rolebindings without matching permissions and without bind is safe from escalation — the authorizer will reject any attempt to bind a role the subject doesn’t already hold. The danger appears when bind is granted broadly (no resourceNames) or when the subject already holds broad permissions.

Guardrail Bypass #3: the impersonate Verb

Impersonation is the most direct escalation of the three because it sidesteps roles entirely. A subject with the impersonate verb can send requests as another user, group, or ServiceAccount, inheriting that identity’s permissions for the request:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: impersonator-danger
rules:
  - apiGroups: [""]
    resources: ["users", "groups", "serviceaccounts"]
    verbs: ["impersonate"]

With that grant, the subject runs:

# Act as a cluster-admin ServiceAccount
kubectl get secrets -A \
  --as=system:serviceaccount:kube-system:some-powerful-sa

# Act as the built-in super-group — instant full admin
kubectl get secrets -A --as-group=system:masters --as=attacker

That second command is the killer. The group system:masters is a hardcoded superuser group in the API server’s authorization layer — members are granted full access regardless of RBAC. (kubeadm also creates a cluster-admin ClusterRoleBinding for it.) So impersonate on groups, unrestricted, is equivalent to handing out cluster-admin.

Lock impersonation down with resourceNames so a subject can impersonate only specific, low-privilege identities — never groups in general:

rules:
  - apiGroups: [""]
    resources: ["serviceaccounts"]
    verbs: ["impersonate"]
    resourceNames: ["limited-audit-sa"]   # this SA only, nothing else

The Sneaky One: Aggregated ClusterRoles

Kubernetes’ built-in admin, edit, and view ClusterRoles are aggregated — their rules are assembled automatically from any ClusterRole carrying the right label, such as rbac.authorization.k8s.io/aggregate-to-admin: "true". The controller merges labelled roles into the aggregate.

That creates a subtle escalation path: if a subject can create clusterroles (even without escalate), they can create a new ClusterRole with the aggregate-to-admin label and inject their chosen rules into admin. Anyone bound to admin — a common, seemingly-safe grant — silently gains those extra permissions.

For a hardening task, restrict who can create ClusterRoles at all, and be suspicious of any workload that needs it. This is exactly the kind of indirect path the CKS likes to hide in a “review this RBAC and fix the over-permission” question.

The Certificate Path (Cross-Domain Escalation)

RBAC isn’t the only route to system:masters. The CertificateSigningRequest (CSR) API is another: a subject who can create CSRs and approve them (certificatesigningrequests/approval + a signer) can mint a client certificate with O=system:masters and authenticate as a full admin — no RBAC binding required, because the group is honored at authentication time.

This connects Cluster Hardening to certificate management. If you want the certificate mechanics, see Kubernetes Certificate Management for the CKA Exam. For CKS, the takeaway is narrower: approve on CSRs plus signing permission is an admin-equivalent grant, so treat it like escalate when you audit a role.

Detecting Escalation: the auth can-i Workflow

You can’t fix what you can’t see. kubectl auth can-i with the impersonation flags (--as, --as-group) lets you ask the API server exactly what a subject is allowed to do — the single most valuable habit for this domain.

# Everything a ServiceAccount can do, as a flat list
kubectl auth can-i --list \
  --as=system:serviceaccount:web:app-sa -n web

# Can this SA do the escalation-critical things?
kubectl auth can-i create clusterrolebindings \
  --as=system:serviceaccount:web:app-sa
kubectl auth can-i escalate clusterroles \
  --as=system:serviceaccount:web:app-sa
kubectl auth can-i impersonate groups \
  --as=system:serviceaccount:web:app-sa

# The blunt "is this basically admin?" check
kubectl auth can-i '*' '*' \
  --as=system:serviceaccount:web:app-sa

A focused audit checklist for any subject you’re reviewing:

Question to askCommand fragmentBad answer
Can it manage bindings?create clusterrolebindingsyes
Can it author roles freely?escalate clusterrolesyes
Can it bind broadly?bind clusterroles (no resourceName)yes
Can it impersonate?impersonate groups / usersyes
Can it mint admin certs?approve certificatesigningrequestsyes
Can it run any pod?create pods in a sensitive namespaceoften yes, investigate

To find who across the cluster holds a dangerous grant, list bindings and inspect the referenced roles, or lean on the ecosystem tools you’re allowed to use in a lab (kubectl-who-can, rbac-tool) — but on the exam, auth can-i --as is always available and always sufficient.

Worked Example: Fixing an Over-Permissioned Role

A classic CKS task hands you a Role and asks you to remove privilege-escalation potential without breaking the app’s real job (say, reading ConfigMaps). You’re given this:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: app-runtime
rules:
  - apiGroups: [""]
    resources: ["configmaps"]
    verbs: ["get", "list"]
  - apiGroups: ["rbac.authorization.k8s.io"]
    resources: ["clusterroles", "clusterrolebindings"]
    verbs: ["create", "escalate", "bind"]     # ⚠️ escalation engine
  - apiGroups: [""]
    resources: ["users", "groups", "serviceaccounts"]
    verbs: ["impersonate"]                     # ⚠️ act as anyone

The fix is to strip everything that isn’t the app’s actual need. The application reads ConfigMaps; it has no business writing RBAC or impersonating identities:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: app-runtime
rules:
  - apiGroups: [""]
    resources: ["configmaps"]
    verbs: ["get", "list"]

Then verify the escalation paths are gone while the real capability remains:

kubectl auth can-i get configmaps \
  --as=system:serviceaccount:web:app-sa          # yes  ✅ still works
kubectl auth can-i escalate clusterroles \
  --as=system:serviceaccount:web:app-sa          # no   ✅ fixed
kubectl auth can-i impersonate groups \
  --as=system:serviceaccount:web:app-sa          # no   ✅ fixed

The mental model to carry into the exam: grant the noun (the resource) and the minimal verbs the app truly uses; never grant a verb that manages RBAC or identity unless the task explicitly requires it.

Hardening Checklist

  • Never grant escalate, bind, or impersonate to a workload ServiceAccount without an explicit, reviewed reason.
  • When bind or impersonate is genuinely needed, constrain it with resourceNames to specific, low-privilege targets.
  • Keep create/update/patch on roles, rolebindings, clusterroles, and clusterrolebindings off application identities.
  • Restrict who can create ClusterRoles to avoid the aggregation-injection path into admin/edit.
  • Treat approve on CSRs plus a signer as admin-equivalent.
  • Audit with kubectl auth can-i --list --as=... and the '*' '*' check before you call a role least-privilege.
  • Pair tight RBAC with a disabled token where the pod never calls the API — see ServiceAccount token security for CKS — so a leaked token has no credential to begin with.
  • Wire up API audit logging so impersonation and binding attempts are recorded; the runtime security guide covers the audit-policy side.
  • Consider an admission guardrail (e.g. a policy that rejects bindings to cluster-admin) via admission control as defense in depth.

Practice on a Real Cluster Before Exam Day

Reading “impersonate on groups equals cluster-admin” is easy; proving it on a live cluster — running kubectl --as-group=system:masters, watching it succeed, then locking it down and confirming the fix with auth can-i — is what makes the knowledge stick under the two-hour clock.

Sailor.sh’s Certified Kubernetes Security Specialist (CKS) Mock Exam Bundle gives you a browser-based, exam-style terminal wired to a real Kubernetes cluster, with Cluster Hardening scenarios that ask you to find and remove escalation paths exactly like the worked example above. It mirrors the exam’s format and time pressure so the reflexes are there when it counts. Sequence it with the CKS study plan, confirm you’ve met the CKS prerequisites, and use the CKS exam topics breakdown to see how Cluster Hardening fits alongside the other domains.

Frequently Asked Questions

What is the difference between the escalate and bind verbs?

escalate applies when you author a Role/ClusterRole: it lets you write rules more powerful than your own permissions, bypassing the authorizer’s escalation-prevention check. bind applies when you create a binding: it lets you reference a role you don’t already fully hold. Authoring vs binding — different steps, different verbs.

Can a user with create rolebindings bind themselves to cluster-admin?

No — not by default. The RBAC authorizer refuses to create a binding to a role the subject doesn’t already possess, unless they have the bind verb on that role. So plain create rolebindings is not, by itself, an escalation to cluster-admin.

Why is impersonating the system:masters group so dangerous?

system:masters is treated as a superuser group in the API server’s authorization layer (and kubeadm binds it to cluster-admin). Any request made as that group is granted full access regardless of RBAC. So an unrestricted impersonate on groups is effectively a cluster-admin grant.

How do I check what permissions a ServiceAccount really has?

Use kubectl auth can-i --list --as=system:serviceaccount:<ns>:<name> -n <ns> for the full list, and targeted checks like kubectl auth can-i escalate clusterroles --as=... for the specific escalation verbs. The --as and --as-group flags let you ask the API server on behalf of any subject.

Are aggregated ClusterRoles really an escalation path?

Yes. Because admin, edit, and view are assembled from labelled ClusterRoles, a subject who can create ClusterRoles can inject rules into admin via the aggregate-to-admin label, silently expanding what everyone bound to admin can do. Restrict ClusterRole creation to prevent it.

How much of the CKS exam involves RBAC?

RBAC lives in the Cluster Hardening area and is one of the most reliably tested skills on the exam. Rather than fixate on a percentage, treat “read a role, spot the escalation path, and remove it with auth can-i proof” as a guaranteed exam muscle — see the CKS exam topics breakdown for how the domains fit together.

Conclusion

Least-privilege RBAC isn’t just about small verbs lists — it’s about refusing the meta-permissions that let a subject rewrite the permission model itself. Learn the three guardrail verbs cold: escalate (author beyond your rights), bind (bind a role you don’t hold), and impersonate (become another identity). Add the RBAC-object write permissions and the CSR-approval path, and you can look at any role and immediately answer the exam’s real question — can this identity give itself more? Prove it with kubectl auth can-i --as, strip what isn’t needed, and you’ve mastered one of the highest-value skills the CKS tests.

Limited Time Offer: Get 80% off all Mock Exam Bundles | Sale ends in 7 days. Start learning today.

Claim Now