Skip to content
CloudOps
All prompts
AI for Kubernetes & Helm Difficulty: Intermediate ClaudeChatGPT

Kubernetes RBAC Audit Prompt

Audit Kubernetes Role, ClusterRole, RoleBinding, and ClusterRoleBinding for excessive permissions, stale bindings, and dangerous wildcards.

Target user
Kubernetes platform engineers and security engineers
Difficulty
Intermediate
Tools
Claude, ChatGPT

The prompt

You are a senior Kubernetes security engineer with deep experience auditing RBAC in production clusters. You know which permissions look harmless and aren't (e.g., `secrets get` = read every credential, `pods/exec create` = arbitrary code execution as the pod's identity).

I will provide:
- Output of `kubectl get clusterrolebindings -o yaml` (or a subset relevant to the audit)
- Output of `kubectl get rolebindings -A -o yaml`
- The specific ClusterRoles / Roles referenced by those bindings
- Optionally: ServiceAccount inventory (`kubectl get sa -A`)
- Audit scope: "all" / specific namespace / specific service account

Your job:

1. **Identify dangerous verbs per resource**:
   - `secrets` + `get/list/watch` → read every credential in scope
   - `pods/exec` + `create` → arbitrary code execution as any pod's SA
   - `pods/attach`, `pods/portforward` → similar privilege escalation paths
   - `*` (wildcard) verb on any resource → effectively admin for that resource
   - `escalate` + `bind` on roles/clusterroles → can grant themselves more
   - `serviceaccounts/token` + `create` → mint tokens as any SA (privilege escalation)
   - `nodes/proxy` → run commands on nodes (effectively node-admin)
   - `certificatesigningrequests` + `approve` → can issue cluster certs
   - `mutatingwebhookconfigurations` / `validatingwebhookconfigurations` + write → can intercept & modify any API request
   - `customresourcedefinitions` + write → can define resources that other controllers act on
2. **Identify dangerous subjects**:
   - `system:authenticated` or `system:unauthenticated` group bindings — broad
   - `system:anonymous` user bindings — extremely broad
   - `default` ServiceAccount bound to anything privileged — pods that don't set `serviceAccountName` get this
   - Stale ServiceAccounts (bound but the SA no longer exists)
3. **Identify dangerous scopes**:
   - ClusterRoleBinding to a "tenant" role that should have been a RoleBinding (cross-namespace privilege)
   - `aggregationRule` ClusterRoles that pull in too many fragments
4. **For each finding** produce: **severity** (critical/high/med/low), **subject**, **role/clusterrole**, **specific verb+resource** of concern, **why it matters**, **suggested fix** as a kubectl diff or yaml patch.
5. **Highlight the "kingmaker" permissions** that allow further privilege escalation, separate from "just" sensitive permissions. The kingmaker set is: `escalate`, `bind`, `impersonate`, `serviceaccounts/token create`, `nodes/proxy`, write on admission webhook configs.
6. **Generate a final summary** with counts per severity and the top 10 most urgent fixes.

Be paranoid but practical — a high-severity finding on a single internal-tooling SA is different from the same finding on `system:authenticated`.

---

Cluster context: [prod / staging / dev / multi-tenant]
Audit scope: [whole cluster / namespace=<X> / service-account=<Y>]
RBAC bindings to audit:
```yaml
[PASTE clusterrolebindings -o yaml]
---
[PASTE rolebindings -A -o yaml]
```
Referenced ClusterRoles / Roles:
```yaml
[PASTE relevant ClusterRoles -o yaml]
```
Optional: SA list with sensitive ones flagged:
```
[PASTE]
```

Why this prompt works

RBAC issues compound silently. A ServiceAccount with secrets get looks fine until you realize that ClusterRoleBinding scopes it across all namespaces — including the one with database credentials. Models tend to evaluate each role in isolation; this prompt forces them to compute effective permissions per subject and flag the kingmaker verbs.

How to use it

  1. Audit by subject, not by role. Pull the full set of bindings for the subject (e.g., a specific SA), then enumerate the union of all roles’ rules.
  2. Group findings by severity. A cluster with 200 ClusterRoles will have many findings — focus the human attention on the critical few.
  3. Test scope assumptions. A RoleBinding referencing a ClusterRole IS scoped to the binding’s namespace — that’s correct and common. A ClusterRoleBinding referencing the same ClusterRole is cluster-wide — that’s where audits usually find problems.
  4. For multi-tenant clusters, audit every namespace that should be isolated; ClusterRoleBindings break tenant boundaries.

Useful commands

# Inventory
kubectl get clusterrolebindings -o yaml > crb.yaml
kubectl get rolebindings -A -o yaml > rb.yaml
kubectl get clusterroles -o yaml > cr.yaml
kubectl get roles -A -o yaml > r.yaml
kubectl get serviceaccounts -A

# Find all bindings for a specific subject
kubectl get clusterrolebindings -o json | jq --arg sa "my-sa" --arg ns "default" \
  '.items[] | select(.subjects[]? | .kind=="ServiceAccount" and .name==$sa and .namespace==$ns)'

# Find ClusterRoles with dangerous verbs
kubectl get clusterroles -o json | \
  jq '.items[] | select(.rules[]? | (.verbs[]? == "*" or .resources[]? == "*")) | .metadata.name'

# Who can do X? (kubectl can-i, on a specific SA)
kubectl auth can-i --as=system:serviceaccount:<ns>:<sa> get secrets -A
kubectl auth can-i --as=system:serviceaccount:<ns>:<sa> create pods/exec -A
kubectl auth can-i --as=system:serviceaccount:<ns>:<sa> '*' '*'

# Use krew plugin: rbac-tool / rbac-lookup
kubectl krew install rbac-tool rbac-lookup
kubectl rbac-tool lookup <name>           # who can do what
kubectl rbac-tool policy-rules -e <subject>  # effective rules
kubectl rbac-tool who-can get secrets -A

# Find unused/stale ServiceAccounts
# (SAs with no bindings or no pods using them)
comm -23 <(kubectl get sa -A -o jsonpath='{range .items[*]}{.metadata.namespace}/{.metadata.name}{"\n"}{end}' | sort) \
         <(kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}/{.spec.serviceAccountName}{"\n"}{end}' | sort -u)

Verb cheatsheet (severity at a glance)

Verb + ResourceSeverityWhy
* * * (any verb, any resource)CriticalCluster admin
get/list/watch secrets *CriticalReads all credentials
create pods/execCriticalArbitrary code execution as the target SA
create serviceaccounts/tokenCriticalMint tokens as any SA — privilege escalation
* nodes or nodes/proxyCriticalNode-level command execution
create/update mutatingwebhookconfigurationsCriticalCan rewrite any request
escalate roles/clusterrolesCriticalCan grant more than they have
bind roles/clusterrolesCriticalCan bind any subject to any role
impersonate users/groups/serviceaccountsCriticalCan act as anyone
create customresourcedefinitionsHighCan install controllers that act on other resources
* deployments, * statefulsetsHighWorkload control = code execution via SA chain
get/list configmapsMediumOften contains config but sometimes secrets
* podsMediumUseful, but couple with pods/exec for escalation

Common findings this catches

  • default SA bound to cluster-admin in a “dev” namespace — every unconfigured pod is cluster admin.
  • system:authenticated group has secrets get cluster-wide — every authenticated user can read every secret.
  • A backup operator with * * * — common but often unnecessary; usually only needs read on most resources + write on its own.
  • Webhook admission controller SA has cluster-admin — webhooks can be powerful with much less.
  • Stale RoleBindings to deleted users — leftover from offboarding; clean up.
  • Aggregated ClusterRoles pulling in fragments via aggregationRule that you didn’t realize granted secrets list.
  • CI/CD SA with create deployments in kube-system — pipeline compromise = cluster compromise.

Minimal-blast-radius fixes

  • Move a ClusterRoleBinding to a RoleBinding when the subject only operates in one namespace.
  • Split a wildcard ClusterRole into a narrower one and re-bind only the verbs needed.
  • Replace * verb with explicit verb list — get,list,watch is usually enough for read-only controllers.
  • Use resourceNames to scope a role to specific named resources where possible (works for get/update/patch/delete, not list or create).

When to escalate

  • A finding that touches a system-critical SA (kube-controller-manager, kubelet, kube-proxy) — coordinate with platform team before changing.
  • Bindings managed by operators / Helm charts / GitOps — fix at the source (chart values, GitOps repo), not by manual kubectl delete.
  • Anything that looks like a defense-in-depth control: removing it may unblock a real attack path even if “looks unused.”

Related prompts

Newsletter

Get weekly AI workflows for DevOps engineers

Practical prompts, automation ideas, and tool reviews for infrastructure engineers. One email per week. No spam.