Limit Use Of The Bind, Impersonate And Escalate Permissions
More Info:
The bind, impersonate, and escalate permissions allow subjects to acquire additional privileges within the cluster. Remove these rights from subjects wherever possible.
Risk Level
High
Address
Security
Compliance Standards
- CIS EKS
Triage and Remediation
- Remediation
Remediation
Manual Steps
-
List all ClusterRoles that grant bind/impersonate/escalate
- Run on: any machine with kubectl access
kubectl get clusterroles -o json | jq -r '.items[]| select(([.rules[].verbs[]?] | contains(["bind"]) or[.rules[].verbs[]?] | contains(["impersonate"]) or[.rules[].verbs[]?] | contains(["escalate"])))| .metadata.name' | sort -u -
Inspect the detailed rules for those ClusterRoles
- Replace
<CLUSTERROLE>with each name from step 1 - Run on: any machine with kubectl access
kubectl get clusterrole <CLUSTERROLE> -o yaml - Replace
-
Identify where these ClusterRoles are bound (who gets these rights)
- For each
<CLUSTERROLE>from step 1, list ClusterRoleBindings and RoleBindings that reference it: - Run on: any machine with kubectl access
# ClusterRoleBindings (cluster-wide subjects)kubectl get clusterrolebindings -o json | jq -r '.items[]| select(.roleRef.kind=="ClusterRole" and .roleRef.name=="<CLUSTERROLE>")| .metadata.name," -> subjects:",(.subjects[]? | " "+.kind+"/"+.name)'# Namespaced RoleBindings granting the ClusterRolefor ns in $(kubectl get ns -o jsonpath='{.items[*].metadata.name}'); doecho "Namespace: $ns"kubectl get rolebindings -n "$ns" -o json | jq -r '.items[]| select(.roleRef.kind=="ClusterRole" and .roleRef.name=="<CLUSTERROLE>")| .metadata.name," -> subjects:",(.subjects[]? | " "+.kind+"/"+.name)'done - For each
-
Decide which subjects truly require bind/impersonate/escalate
- For each binding found in step 3:
- Confirm whether the subject (user/group/serviceaccount) is an infrastructure component or automation that must:
- create/modify RoleBindings/ClusterRoleBindings (needs
bind), - act on behalf of other users (needs
impersonate), - change privilege levels or assign high-privilege roles (needs
escalate).
- create/modify RoleBindings/ClusterRoleBindings (needs
- Mark each subject as:
- “Required” (document the justification), or
- “Excess” (should be removed or replaced with a less-privileged role).
- Confirm whether the subject (user/group/serviceaccount) is an infrastructure component or automation that must:
- For each binding found in step 3:
-
Remove or reduce excessive permissions from bindings and/or roles
- To remove a subject from a binding (safer than deleting the role):
- Run on: any machine with kubectl access
# Edit binding and remove the subject entrykubectl edit clusterrolebinding <BINDING_NAME># or, for namespaced:kubectl edit rolebinding <BINDING_NAME> -n <NAMESPACE>- If a ClusterRole is used only to provide bind/impersonate/escalate and is no longer needed:
kubectl delete clusterrole <CLUSTERROLE>- Alternatively, edit the ClusterRole to remove those verbs from its rules:
kubectl edit clusterrole <CLUSTERROLE># In the editor, remove "bind", "impersonate", and/or "escalate" from .rules[].verbs -
Verify that bind/impersonate/escalate are now limited
- Re-run the initial discovery and ensure only justified, documented roles remain:
kubectl get clusterroles -o json | jq -r '.items[]| select(([.rules[].verbs[]?] | contains(["bind"]) or[.rules[].verbs[]?] | contains(["impersonate"]) or[.rules[].verbs[]?] | contains(["escalate"])))| .metadata.name' | sort -u- For any remaining roles listed, confirm that their bindings (step 3) match the “Required” subjects decided in step 4.
Using kubectl
# 1) List all ClusterRoles that grant bind/impersonate/escalate
# Run on: any machine with kubectl access
kubectl get clusterroles -o json | jq -r '
.items[]
| select(
# Rules that mention these sensitive verbs
(.rules[]? | (.verbs[]? | IN("bind","impersonate","escalate")))
# Or rules that target the SubjectAccessReview APIs (strong signal of privilege logic)
or (.rules[]? | (.resources[]? | test("subjectaccessreview"; "i")))
)
| .metadata.name
' | sort -u
Problem indication:
Any ClusterRole shown here is potentially sensitive and needs manual review.
# 2) Show full details of each potentially sensitive ClusterRole
# Replace <CLUSTERROLE_NAME> with each name from the previous command.
kubectl get clusterrole <CLUSTERROLE_NAME> -o yaml
What to look for:
Within rules::
- Problematic verbs:
verbs: ["bind"]verbs: ["impersonate"]verbs: ["escalate"]
- Problematic resources (often combined with above verbs):
resources: ["clusterroles", "roles"]withbindresourcesincludingsubjectaccessreviews,selfsubjectaccessreviews,localsubjectaccessreviewswith wide verbs like["create","update","*"]
- Excessive wildcards:
verbs: ["*"]resources: ["*"]orapiGroups: ["*"]
These indicate the role can grant or exercise extra privileges and must be justified.
# 3) Find which subjects are bound to these sensitive ClusterRoles
# For each <CLUSTERROLE_NAME> from step 1:
kubectl get clusterrolebindings -o json | jq -r '
.items[]
| select(.roleRef.kind == "ClusterRole" and .roleRef.name == "<CLUSTERROLE_NAME>")
| .metadata.name
'
# 4) Inspect each ClusterRoleBinding to see who gets these rights
kubectl get clusterrolebinding <BINDING_NAME> -o yaml
What to look for in bindings (subjects:):
- Broad subjects:
kind: Group,name: system:authenticatedorsystem:serviceaccountskind: ServiceAccountwithout namespace scoping in your manifests/IaC
- Service accounts or users not clearly part of a privileged admin/CI/CD function.
Bindings that give these roles to wide groups or non-admin workloads are strong problems.
# 5) Also check namespace-scoped Roles (less common but possible)
kubectl get roles --all-namespaces -o json | jq -r '
.items[]
| select(.rules[]? | (.verbs[]? | IN("bind","impersonate","escalate")))
| "\(.metadata.namespace)/\(.metadata.name)"
' | sort
# 6) Show each flagged Role and its RoleBindings
# Inspect Role:
kubectl get role -n <NAMESPACE> <ROLE_NAME> -o yaml
# Find RoleBindings using that Role:
kubectl get rolebindings -n <NAMESPACE> -o json | jq -r '
.items[]
| select(.roleRef.kind == "Role" and .roleRef.name == "<ROLE_NAME>")
| .metadata.name
'
# Inspect each RoleBinding:
kubectl get rolebinding -n <NAMESPACE> <BINDING_NAME> -o yaml
Problem indication:
Namespace Roles that grant these verbs to regular application service accounts or broad groups should be treated as misconfigurations unless there is a clear, documented need.
Verification after manual review/changes
After you manually adjust roles/bindings (via edited manifests/IaC):
# Re-run the discovery to confirm remaining usage is limited and intentional
kubectl get clusterroles -o json | jq -r '
.items[]
| select(.rules[]? | (.verbs[]? | IN("bind","impersonate","escalate")))
| .metadata.name
' | sort -u
You should be able to account for every remaining ClusterRole listed and validate that only strictly necessary, well-justified subjects are bound to them.
Automation
#!/usr/bin/env bash
#
# Report ClusterRoles and Roles that grant:
# - verbs: impersonate, bind, escalate
# - or broad RBAC rights that include those verbs via wildcards
#
# Run on: any machine with kubectl access to the cluster
# Requirements: kubectl, jq, grep, awk, sed
set -euo pipefail
# Helper: header
hdr() {
echo
echo "============================================================"
echo "$1"
echo "============================================================"
}
# 1) Raw RBAC objects with explicit impersonate/bind/escalate verbs
hdr "1) ClusterRoles WITH explicit impersonate/bind/escalate verbs"
kubectl get clusterroles -o json \
| jq -r '
.items[]
| {name: .metadata.name, rules: .rules}
| select(
.rules != null and
(.rules[]
| select(.verbs != null)
| .verbs[]
| IN("impersonate","bind","escalate"))
)
| .name
' | sort -u || true
hdr "2) Roles WITH explicit impersonate/bind/escalate verbs (namespaced)"
kubectl get roles --all-namespaces -o json \
| jq -r '
.items[]
| {ns: .metadata.namespace, name: .metadata.name, rules: .rules}
| select(
.rules != null and
(.rules[]
| select(.verbs != null)
| .verbs[]
| IN("impersonate","bind","escalate"))
)
| "\(.ns)/\(.name)"
' | sort -u || true
# 2) RBAC objects that may indirectly allow these verbs via wildcards
hdr "3) ClusterRoles that use wildcard verbs or resources (potentially risky)"
kubectl get clusterroles -o json \
| jq -r '
.items[]
| {name: .metadata.name, rules: .rules}
| select(
.rules != null and
(.rules[]
| ( (.verbs != null and (.verbs[] == "*"))
or (.resources != null and (.resources[] == "*"))
or (.apiGroups != null and (.apiGroups[] == "*"))
)
)
)
| .name
' | sort -u || true
hdr "4) Roles that use wildcard verbs or resources (namespaced, potentially risky)"
kubectl get roles --all-namespaces -o json \
| jq -r '
.items[]
| {ns: .metadata.namespace, name: .metadata.name, rules: .rules}
| select(
.rules != null and
(.rules[]
| ( (.verbs != null and (.verbs[] == "*"))
or (.resources != null and (.resources[] == "*"))
or (.apiGroups != null and (.apiGroups[] == "*"))
)
)
)
| "\(.ns)/\(.name)"
' | sort -u || true
# 3) Subjects that are bound to these risky roles
hdr "5) ClusterRoleBindings that reference risky ClusterRoles"
# First, compute set of risky ClusterRoles
readarray -t risky_crs < <(
{
kubectl get clusterroles -o json \
| jq -r '
.items[]
| {name: .metadata.name, rules: .rules}
| select(
.rules != null and
(.rules[]
| select(.verbs != null)
| .verbs[]
| IN("impersonate","bind","escalate"))
)
| .name
' ;
kubectl get clusterroles -o json \
| jq -r '
.items[]
| {name: .metadata.name, rules: .rules}
| select(
.rules != null and
(.rules[]
| ( (.verbs != null and (.verbs[] == "*"))
or (.resources != null and (.resources[] == "*"))
or (.apiGroups != null and (.apiGroups[] == "*"))
)
)
)
| .name
'
} | sort -u
)
if ((${#risky_crs[@]} == 0)); then
echo "No risky ClusterRoles detected."
else
printf '%s\n' "${risky_crs[@]}" > /tmp/risky_clusterroles.txt
kubectl get clusterrolebindings -o json \
| jq -r '
.items[]
| {name: .metadata.name, roleRef: .roleRef, subjects: .subjects}
| select(.roleRef.kind == "ClusterRole")
| "\(.roleRef.name) \(.name)"
' \
| while read -r role binding; do
if grep -qx "$role" /tmp/risky_clusterroles.txt; then
echo "ClusterRoleBinding: $binding (role: $role)"
kubectl get clusterrolebinding "$binding" -o yaml
echo "------------------------------------------------------------"
fi
done
fi
hdr "6) RoleBindings that reference risky Roles (namespaced)"
# Compute set of risky Roles
readarray -t risky_roles < <(
{
kubectl get roles --all-namespaces -o json \
| jq -r '
.items[]
| {ns: .metadata.namespace, name: .metadata.name, rules: .rules}
| select(
.rules != null and
(.rules[]
| select(.verbs != null)
| .verbs[]
| IN("impersonate","bind","escalate"))
)
| "\(.ns)/\(.name)"
' ;
kubectl get roles --all-namespaces -o json \
| jq -r '
.items[]
| {ns: .metadata.namespace, name: .metadata.name, rules: .rules}
| select(
.rules != null and
(.rules[]
| ( (.verbs != null and (.verbs[] == "*"))
or (.resources != null and (.resources[] == "*"))
or (.apiGroups != null and (.apiGroups[] == "*"))
)
)
)
| "\(.ns)/\(.name)"
'
} | sort -u
)
if ((${#risky_roles[@]} == 0)); then
echo "No risky namespaced Roles detected."
else
printf '%s\n' "${risky_roles[@]}" > /tmp/risky_roles.txt
kubectl get rolebindings --all-namespaces -o json \
| jq -r '
.items[]
| {ns: .metadata.namespace, name: .metadata.name, roleRef: .roleRef}
| select(.roleRef.kind == "Role")
| "\(.ns) \(.name) \(.roleRef.name)"
' \
| while read -r ns binding role; do
if grep -qx "${ns}/${role}" /tmp/risky_roles.txt; then
echo "RoleBinding: ${ns}/${binding} (role: ${ns}/${role})"
kubectl -n "$ns" get rolebinding "$binding" -o yaml
echo "------------------------------------------------------------"
fi
done
fi
hdr "SUMMARY"
echo "1) Any ClusterRole or Role listed in sections 1 and 2 DEFINITELY uses impersonate/bind/escalate."
echo "2) Any role listed in sections 3 and 4 uses wildcards and MAY implicitly allow those verbs."
echo "3) Sections 5 and 6 show which subjects (users, groups, service accounts) are bound to risky roles."
echo
echo "Review each risky role and its bindings and remove impersonate/bind/escalate where not strictly required."
Explanation of output that indicates a problem:
- Section 1 and 2: Any ClusterRole or Role listed here explicitly includes
impersonate,bind, orescalatein.rules[].verbs. These are directly problematic and must be reviewed; remove those verbs unless strictly necessary. - Section 3 and 4: ClusterRoles/Roles listed here use
*inverbs,resources, orapiGroups. These broad grants may indirectly allow impersonation or privilege escalation; they should be narrowed or redesigned. - Section 5 and 6: For each risky role, these sections show the RoleBindings/ClusterRoleBindings and their subjects. If high-privilege or many subjects are bound (e.g., generic groups like
system:authenticated), that indicates higher risk.