Limit Use Of The Bind, Impersonate And Escalate Permissions
More Info:
The bind, impersonate and escalate RBAC verbs allow subjects to grant themselves or others additional privileges. Restrict them tightly.
Risk Level
High
Address
Security
Compliance Standards
- CIS Kubernetes
Triage and Remediation
- Remediation
Remediation
Manual Steps
-
List all ClusterRoles/roles using bind, impersonate, or escalate
- On any machine with kubectl access:
kubectl get clusterroles -o json | \jq -r '.items[]| select(.rules[]?| any(.verbs[]?; .=="bind" or .=="escalate" or .=="impersonate"))| .metadata.name'kubectl get roles --all-namespaces -o json | \jq -r '.items[]| select(.rules[]?| any(.verbs[]?; .=="bind" or .=="escalate" or .=="impersonate"))| "\(.metadata.namespace):\(.metadata.name)"'
- Save the outputs; these are the RBAC definitions to review.
- On any machine with kubectl access:
-
Inspect the privileges and intended use of each risky role
- For each ClusterRole name from step 1:
kubectl get clusterrole <CLUSTERROLE_NAME> -o yaml
- For each namespaced Role (namespace:name) from step 1:
kubectl get role <ROLE_NAME> -n <NAMESPACE> -o yaml
- Manually determine:
- Which subjects (users/groups/serviceaccounts) are supposed to have these capabilities, if any.
- Whether these verbs are strictly required for the role’s intended function (e.g., controller that must create/modify RBAC).
- For each ClusterRole name from step 1:
-
Identify who can use those roles via bindings
- For each risky ClusterRole:
kubectl get clusterrolebindings -o json | \jq -r '.items[]| select(.roleRef.kind=="ClusterRole" and .roleRef.name=="<CLUSTERROLE_NAME>")| .metadata.name'kubectl get clusterrolebinding <BINDING_NAME> -o yaml
- For each risky namespaced Role:
kubectl get rolebindings --all-namespaces -o json | \jq -r '.items[]| select(.roleRef.kind=="Role" and .roleRef.name=="<ROLE_NAME>")| "\(.metadata.namespace):\(.metadata.name)"'kubectl get rolebinding <BINDING_NAME> -n <NAMESPACE> -o yaml
- Manually review whether each bound subject truly needs bind/impersonate/escalate.
- For each risky ClusterRole:
-
Decide on least‑privilege changes per role and binding
For each role/binding you reviewed, choose one of:- Remove the dangerous verbs entirely if not strictly needed: edit the role and delete
bind,escalate, andimpersonatefrom theverbslist.kubectl edit clusterrole <CLUSTERROLE_NAME># orkubectl edit role <ROLE_NAME> -n <NAMESPACE> - Scope down subjects if the verbs are needed only for a very small set of trusted identities:
- Remove unnecessary subjects from the corresponding ClusterRoleBinding/RoleBinding.
kubectl edit clusterrolebinding <BINDING_NAME># orkubectl edit rolebinding <BINDING_NAME> -n <NAMESPACE>
- Remove unnecessary subjects from the corresponding ClusterRoleBinding/RoleBinding.
- Split roles: create a separate role without these verbs for most users, keeping bind/impersonate/escalate only in a dedicated, tightly bound role for specific automation or administrators (via manifest updates or
kubectl apply -f).
- Remove the dangerous verbs entirely if not strictly needed: edit the role and delete
-
Re-apply or create updated RBAC manifests (if using GitOps/IaC)
- If your cluster uses manifests as the source of truth, mirror the edits from step 4 into your RBAC YAML and re-apply:
kubectl apply -f <UPDATED_RBAC_MANIFEST.yaml>
- Ensure CI/GitOps will not reintroduce the removed verbs or bindings.
- If your cluster uses manifests as the source of truth, mirror the edits from step 4 into your RBAC YAML and re-apply:
-
Verify that risky verbs are now limited to explicitly approved roles
- Re-run the evidence commands from step 1 on any machine with kubectl:
kubectl get clusterroles -o json | \jq -r '.items[]| select(.rules[]?| any(.verbs[]?; .=="bind" or .=="escalate" or .=="impersonate"))| .metadata.name'kubectl get roles --all-namespaces -o json | \jq -r '.items[]| select(.rules[]?| any(.verbs[]?; .=="bind" or .=="escalate" or .=="impersonate"))| "\(.metadata.namespace):\(.metadata.name)"'
- Manually confirm that:
- Only the minimal, explicitly justified roles still include these verbs.
- Their bindings grant access only to tightly controlled, trusted subjects.
- Re-run the evidence commands from step 1 on any machine with kubectl:
Using kubectl
# 1) List all ClusterRoles that include bind, impersonate, or escalate
# Run on: any machine with kubectl access
kubectl get clusterroles -o json | jq -r '
.items[]
| select(
[.rules[].verbs[]?] | inside(["bind"]) or
[.rules[].verbs[]?] | inside(["impersonate"]) or
[.rules[].verbs[]?] | inside(["escalate"])
)
| .metadata.name'
Problem indication: Any ClusterRole name returned here has at least one of the sensitive verbs and must be reviewed.
# 2) Inspect details of each suspicious ClusterRole (replace NAME with one from above)
kubectl get clusterrole NAME -o yaml
What to look for (problem indication):
verbscontainingbind,impersonate, orescalate.- Combined with broad resources, for example:
resources: ["*"]apiGroups: ["*"]
- Or high‑risk targets such as:
resources: ["clusterroles","roles","clusterrolebindings","rolebindings","serviceaccounts","users","groups"]
- Use by subjects that are not tightly controlled (see next commands).
# 3) See which ClusterRoleBindings and RoleBindings use those ClusterRoles
# Run once to get all bindings that reference sensitive-verb ClusterRoles
for cr in $(kubectl get clusterroles -o json | jq -r '
.items[]
| select(
[.rules[].verbs[]?] | inside(["bind"]) or
[.rules[].verbs[]?] | inside(["impersonate"]) or
[.rules[].verbs[]?] | inside(["escalate"])
)
| .metadata.name'); do
echo "=== Bindings for ClusterRole: $cr ==="
kubectl get clusterrolebindings -o json | jq -r --arg CR "$cr" '
.items[]
| select(.roleRef.kind=="ClusterRole" and .roleRef.name==$CR)
| .metadata.name + " (ClusterRoleBinding)"'
kubectl get rolebindings --all-namespaces -o json | jq -r --arg CR "$cr" '
.items[]
| select(.roleRef.kind=="ClusterRole" and .roleRef.name==$CR)
| .metadata.namespace + "/" + .metadata.name + " (RoleBinding)"'
done
Problem indication: Sensitive-verb ClusterRoles bound to:
subjectswithkind: ServiceAccountin broad or default namespaces,kind: Userorkind: Grouprepresenting general developer or CI users, not a small, trusted admin set.
# 4) Inspect specific bindings and their subjects (replace NAME/NAMESPACE)
kubectl get clusterrolebinding NAME -o yaml
kubectl get rolebinding NAME -n NAMESPACE -o yaml
Problem indication:
subjectsthat are many or loosely defined (e.g.,system:authenticated, large teams, generic service accounts).- Any non‑break‑glass / non‑cluster‑admin identity holding these permissions.
# 5) Check for impersonation permissions specifically
kubectl get clusterroles -o json | jq -r '
.items[]
| select(
any(.rules[]?; any(.verbs[]?; .=="impersonate"))
)
| .metadata.name as $name
| "ClusterRole: \($name)"'
Then, as in steps 2–4, inspect:
kubectl get clusterrole <NAME> -o yaml
kubectl get clusterrolebindings --all-namespaces -o yaml | \
yq 'select(.roleRef.kind=="ClusterRole" and .roleRef.name=="<NAME>")'
kubectl get rolebindings --all-namespaces -o yaml | \
yq 'select(.roleRef.kind=="ClusterRole" and .roleRef.name=="<NAME>")'
Problem indication: impersonate on users, groups, or serviceaccounts granted to any subject that is not a strictly controlled admin/break‑glass identity.
# 6) Quick summary table of all sensitive-verb ClusterRoles and which verbs they use
kubectl get clusterroles -o json | jq -r '
.items[]
| {name: .metadata.name, rules: .rules}
| select(.rules != null)
| .name as $n
| ([.rules[].verbs[]?] | unique) as $verbs
| select(any($verbs[]; .=="bind" or .=="impersonate" or .=="escalate"))
| "\($n): \($verbs | join(","))"'
Problem indication: Roles with multiple sensitive verbs or with these verbs in roles that are not clearly “admin‑only” are higher‑risk and should be candidates for restriction or redesign.
Automation
#!/usr/bin/env bash
# Report ClusterRoles and Roles that grant bind / impersonate / escalate,
# and which subjects can use them (directly or via RoleBindings/ClusterRoleBindings).
set -euo pipefail
echo "=== 1) ClusterRoles with bind/impersonate/escalate verbs ==="
kubectl get clusterroles -o json \
| jq -r '
.items[]
| {name: .metadata.name, rules: .rules}
| select(
.rules != null and
([.rules[].verbs[]?] | inside(["bind","impersonate","escalate"]) or
(.rules[]? | .verbs[]? as $v | select($v=="bind" or $v=="impersonate" or $v=="escalate")))
)
| "ClusterRole: \(.name)\nRules:\n\(.rules | tojson)\n---"
'
echo
echo "=== 2) Namespaced Roles with bind/impersonate/escalate verbs ==="
kubectl get roles --all-namespaces -o json \
| jq -r '
.items[]
| {ns: .metadata.namespace, name: .metadata.name, rules: .rules}
| select(
.rules != null and
([.rules[].verbs[]?] | inside(["bind","impersonate","escalate"]) or
(.rules[]? | .verbs[]? as $v | select($v=="bind" or $v=="impersonate" or $v=="escalate")))
)
| "Role: \(.ns)/\(.name)\nRules:\n\(.rules | tojson)\n---"
'
echo
echo "=== 3) ClusterRoleBindings referencing those high-privilege ClusterRoles ==="
# First collect ClusterRoles that have the sensitive verbs
high_priv_crs=$(kubectl get clusterroles -o json \
| jq -r '
.items[]
| select(
.rules != null and
([.rules[].verbs[]?] | inside(["bind","impersonate","escalate"]) or
(.rules[]? | .verbs[]? as $v | select($v=="bind" or $v=="impersonate" or $v=="escalate")))
)
| .metadata.name
' | sort -u)
if [ -n "$high_priv_crs" ]; then
# shellcheck disable=SC2086
kubectl get clusterrolebindings -o json \
| jq -r --argjson crs "$(printf '%s\n' $high_priv_crs | jq -R . | jq -s .)" '
.items[]
| select(.roleRef.kind=="ClusterRole" and (.roleRef.name as $n | $crs | index($n)))
| "ClusterRoleBinding: \(.metadata.name)\n RoleRef: \(.roleRef.kind)/\(.roleRef.name)\n Subjects: \(.subjects // [] | tojson)\n---"
'
else
echo "No ClusterRoles with bind/impersonate/escalate verbs found."
fi
echo
echo "=== 4) RoleBindings referencing high-privilege Roles ==="
# Collect Roles that have the sensitive verbs
high_priv_roles=$(kubectl get roles --all-namespaces -o json \
| jq -r '
.items[]
| select(
.rules != null and
([.rules[].verbs[]?] | inside(["bind","impersonate","escalate"]) or
(.rules[]? | .verbs[]? as $v | select($v=="bind" or $v=="impersonate" or $v=="escalate")))
)
| .metadata.namespace + "/" + .metadata.name
' | sort -u)
if [ -n "$high_priv_roles" ]; then
kubectl get rolebindings --all-namespaces -o json \
| jq -r --argjson roles "$(printf '%s\n' $high_priv_roles | jq -R . | jq -s .)" '
.items[]
| . as $rb
| ($rb.roleRef.kind + ":" + $rb.metadata.namespace + "/" + $rb.roleRef.name) as $key
| select(
($rb.roleRef.kind=="Role") and
($roles | map("Role:" + .) | index($key))
)
| "RoleBinding: \(.metadata.namespace)/\(.metadata.name)\n RoleRef: \(.roleRef.kind)/\(.roleRef.name)\n Subjects: \(.subjects // [] | tojson)\n---"
'
else
echo "No Roles with bind/impersonate/escalate verbs found."
fi
echo
echo "=== Interpretation ==="
cat <<'EOF'
Potential problems indicated by this report:
- Any ClusterRole or Role listed in sections (1) or (2) that is not strictly required.
- Any ClusterRoleBinding or RoleBinding in sections (3) or (4) that grants these verbs to:
* broad groups (e.g., system:authenticated, system:masters, or large custom groups)
* service accounts in general-purpose namespaces
* end-user identities that do not administer RBAC
These entries should be reviewed manually. Where possible, remove bind/impersonate/escalate
from the role, or narrow/remove the bindings that grant access to such roles.
EOF
Run this from any machine with kubectl access.
Problematic output is any role giving ["bind","impersonate","escalate"] (alone or among other verbs) to non-essential admin identities or broad subjects, especially in shared or application namespaces.