Limit Use Of Bind Impersonate And Escalate Permissions
More Info:
Cluster roles and roles with the impersonate, bind or escalate permissions should not be granted unless strictly required. Each of these permissions allow a particular subject to escalate their privileges beyond those explicitly granted by cluster administrators
Risk Level
Medium
Address
Security
Compliance Standards
- CIS Kubernetes
Triage and Remediation
- Remediation
Remediation
Manual Steps
-
List all Roles/ClusterRoles that grant
bind,escalate, orimpersonate.- Run on: any machine with kubectl access
- Command:
kubectl get clusterroles -o json | jq -r '.items[]| select((.rules // [])| map((.verbs // [])| map(. == "bind" or . == "escalate" or . == "impersonate")| any))| .metadata.name'kubectl get roles --all-namespaces -o json | jq -r '.items[]| select((.rules // [])| map((.verbs // [])| map(. == "bind" or . == "escalate" or . == "impersonate")| any))| [.metadata.namespace, .metadata.name] | @tsv'
-
Identify which subjects (users, groups, service accounts) are bound to those high‑risk Roles/ClusterRoles.
- Run on: any machine with kubectl access
- Command:
Then correlate with the list from step 1:kubectl get clusterrolebindings -o json | jq -r '.items[]| . as $crb| ($crb.roleRef.name) as $role| $role as $r| $r' | sort -ukubectl get clusterrolebindings -o json | jq -r '.items[]| select(.roleRef.kind == "ClusterRole")| . as $crb| $crb.roleRef.name as $role| $crb.subjects[]? as $s| [$role, $s.kind, $s.namespace // "", $s.name] | @tsv'kubectl get rolebindings --all-namespaces -o json | jq -r '.items[]| . as $rb| [$rb.metadata.namespace, $rb.roleRef.kind, $rb.roleRef.name] as $info| $rb.subjects[]? as $s| [$info[], $s.kind, $s.namespace // "", $s.name] | @tsv'
-
Review business and technical justification for each subject with these permissions.
- For each subject identified in step 2, determine:
- Why do they need
bind,escalate, orimpersonate? - Is it documented and approved (e.g., admin break-glass, CI/CD controller, identity broker)?
- Why do they need
- If no clear, minimal justification exists, mark that binding for removal or reduction (e.g., to a narrower role without these verbs).
- For each subject identified in step 2, determine:
-
Remove or tighten unnecessary
bind/escalate/impersonatepermissions.- Run on: any machine with kubectl access
- To remove a binding entirely (example – replace with actual names from your review):
kubectl delete clusterrolebinding <clusterrolebinding-name>kubectl delete rolebinding -n <namespace> <rolebinding-name>
- To edit and drop only the risky verbs from an otherwise needed role:
orkubectl edit clusterrole <clusterrole-name>Then removekubectl edit role -n <namespace> <role-name>
bind,escalate, andimpersonatefrom.rules[].verbswhile preserving required non‑escalating verbs.
-
If a subject genuinely needs some of these rights, scope them as narrowly as possible.
- Prefer dedicated, minimal Roles/ClusterRoles with just the necessary resources and verbs (e.g., only impersonate specific users/groups, only bind to a specific role).
- Create/update via manifest so the intent is explicit (example skeleton):
apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata:name: scoped-impersonatorrules:- apiGroups: [""]resources: ["users"]resourceNames: ["specific-user"]verbs: ["impersonate"]
- Apply:
kubectl apply -f scoped-impersonator.yaml
-
Verify that high‑risk verbs are now only where explicitly approved.
- Run on: any machine with kubectl access
- Re-run the discovery from step 1 and confirm the remaining Roles/ClusterRoles with
bind,escalate, orimpersonatematch your approved list:kubectl get clusterroles -o json | jq -r '.items[]| select((.rules // [])| map((.verbs // [])| map(. == "bind" or . == "escalate" or . == "impersonate")| any))| .metadata.name'kubectl get roles --all-namespaces -o json | jq -r '.items[]| select((.rules // [])| map((.verbs // [])| map(. == "bind" or . == "escalate" or . == "impersonate")| any))| [.metadata.namespace, .metadata.name] | @tsv'
Using kubectl
# 1) List all ClusterRoles that contain bind, impersonate, or escalate
# Run on: any machine with kubectl access
kubectl get clusterroles -o json | jq -r '
.items[]
| select(
[.rules[].verbs?] | flatten | map(tostring)
| any(. == "bind" or . == "impersonate" or . == "escalate")
)
| .metadata.name
'
Problem indication:
Any ClusterRole name returned by this command includes at least one of the sensitive verbs. These roles need review to see who is bound to them and whether this is strictly required.
# 2) Show full definitions of ClusterRoles with these verbs
for cr in $(kubectl get clusterroles -o json | jq -r '
.items[]
| select(
[.rules[].verbs?] | flatten | map(tostring)
| any(. == "bind" or . == "impersonate" or . == "escalate")
)
| .metadata.name
'); do
echo "### ClusterRole: $cr"
kubectl get clusterrole "$cr" -o yaml
echo
done
Problem indication:
Within each role’s .rules:
verbscontainingbind,escalate, orimpersonateagainst broadresources(e.g.,*,clusterroles,users,groups) orresourceNamesnot narrowly scoped is higher risk.
These should be justified by a concrete operational need.
# 3) Find RoleBindings that refer to those ClusterRoles
# (who gets these powerful ClusterRoles, across all namespaces)
for cr in $(kubectl get clusterroles -o json | jq -r '
.items[]
| select(
[.rules[].verbs?] | flatten | map(tostring)
| any(. == "bind" or . == "impersonate" or . == "escalate")
)
| .metadata.name
'); do
echo "### RoleBindings referencing ClusterRole: $cr"
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] | @tsv
' | column -t
echo
done
Problem indication:
Any RoleBinding shown here grants a subject (user, group, or ServiceAccount) access to a ClusterRole that has bind, impersonate, or escalate. Each binding must be checked for least-privilege necessity.
# 4) Find ClusterRoleBindings that refer to those ClusterRoles
for cr in $(kubectl get clusterroles -o json | jq -r '
.items[]
| select(
[.rules[].verbs?] | flatten | map(tostring)
| any(. == "bind" or . == "impersonate" or . == "escalate")
)
| .metadata.name
'); do
echo "### ClusterRoleBindings referencing ClusterRole: $cr"
kubectl get clusterrolebindings -o json | jq -r --arg CR "$cr" '
.items[]
| select(.roleRef.kind == "ClusterRole" and .roleRef.name == $CR)
| .metadata.name
'
echo
done
Problem indication:
ClusterRoleBindings are cluster-wide. Any binding here grants powerful permissions everywhere; these are high-risk and should be tightly justified and, where possible, replaced with narrower, namespace-scoped permissions.
# 5) Inspect the subjects for each risky binding (who exactly has them)
echo "### ClusterRoleBindings with subjects and sensitive verbs"
kubectl get clusterroles,clusterrolebindings,rolebindings --all-namespaces -o json | jq -r '
def has_sensitive_verbs:
(.rules // [])
| map(.verbs // [])
| flatten
| map(tostring)
| any(. == "bind" or . == "impersonate" or . == "escalate");
.items[]
| select(.kind == "ClusterRole" and has_sensitive_verbs) as $cr
| $cr.metadata.name as $crName
| $cr
|
(
# ClusterRoleBindings
(input // empty)
| .items[]
| select(.kind == "ClusterRoleBinding" and .roleRef.kind == "ClusterRole" and .roleRef.name == $crName)
| "ClusterRole: \($crName) | ClusterRoleBinding: \(.metadata.name) | Subjects: \(.subjects // [] | map(.kind + \"/\" + .name) | join(\",\"))"
)' 2>/dev/null
(If the combined jq is too complex in your environment, manually inspect each binding found in steps 3 and 4 using kubectl get <binding> -o yaml.)
Problem indication:
Look for:
- Subjects that are broad (e.g.,
system:authenticated,system:serviceaccounts, large groups). - Service accounts used by application workloads rather than dedicated infrastructure/automation components.
- Human users or groups who do not administratively need to bind/impersonate/escalate.
# 6) Verify after review and changes (re-run discovery)
kubectl get clusterroles -o json | jq -r '
.items[]
| select(
[.rules[].verbs?] | flatten | map(tostring)
| any(. == "bind" or . == "impersonate" or . == "escalate")
)
| .metadata.name
'
Verification interpretation:
- If this returns no ClusterRole names, no ClusterRole currently declares
bind,impersonate, orescalate. - If it still returns entries, those roles (and their bindings) remain and must be consciously accepted or further reduced.
Automation
#!/usr/bin/env bash
# Report Roles/ClusterRoles and their bindings that grant bind/impersonate/escalate
# Run on: any machine with kubectl access and current-context set to target cluster
set -euo pipefail
echo "=== 1) Roles and ClusterRoles containing bind/impersonate/escalate verbs ==="
echo
# List ClusterRoles with these verbs
echo "--- ClusterRoles with bind/impersonate/escalate ---"
kubectl get clusterroles -o json \
| jq -r '
.items[]
| . as $cr
| ($cr.rules // [])
| map(
select(
(.verbs // [])
| map(ascii_downcase)
| map(select(. == "bind" or . == "impersonate" or . == "escalate"))
| length > 0
)
)
| select(length > 0)
| $cr.metadata.name
' | sort -u
echo
# List Roles per-namespace with these verbs
echo "--- Roles with bind/impersonate/escalate (namespaced) ---"
kubectl get roles --all-namespaces -o json \
| jq -r '
.items[]
| . as $r
| ($r.rules // [])
| map(
select(
(.verbs // [])
| map(ascii_downcase)
| map(select(. == "bind" or . == "impersonate" or . == "escalate"))
| length > 0
)
)
| select(length > 0)
| "\($r.metadata.namespace)\t\($r.metadata.name)"
' | sort -u
echo
echo "=== 2) ClusterRoleBindings that reference ClusterRoles above ==="
echo
# Capture suspect clusterroles for reuse
suspect_crs=$(kubectl get clusterroles -o json \
| jq -r '
.items[]
| . as $cr
| ($cr.rules // [])
| map(
select(
(.verbs // [])
| map(ascii_downcase)
| map(select(. == "bind" or . == "impersonate" or . == "escalate"))
| length > 0
)
)
| select(length > 0)
| $cr.metadata.name
' | sort -u)
if [ -z "$suspect_crs" ]; then
echo "No ClusterRoles with bind/impersonate/escalate verbs found."
else
echo "ClusterRoles with sensitive verbs: "
printf ' %s\n' $suspect_crs
echo
echo "ClusterRoleBindings granting these ClusterRoles:"
kubectl get clusterrolebindings -o json \
| jq -r --argjson crs "$(printf '%s\n' $suspect_crs | jq -R . | jq -s .)" '
.items[]
| select(.roleRef.kind == "ClusterRole")
| select(.roleRef.name as $rn | $crs | index($rn) != null)
| .metadata.name as $crb
| .roleRef.name as $role
| (.subjects // [])[]?
| "\($crb)\t\($role)\t\(.kind)\t\(.namespace // "-")\t\(.name)"
' | sort -u \
| awk 'BEGIN { OFS="\t"; print "CRB_NAME","CLUSTERROLE","SUBJECT_KIND","SUBJECT_NAMESPACE","SUBJECT_NAME" } 1'
fi
echo
echo "=== 3) RoleBindings that reference Roles above (namespaced) ==="
echo
# Capture suspect roles (namespaced)
suspect_roles=$(kubectl get roles --all-namespaces -o json \
| jq -r '
.items[]
| . as $r
| ($r.rules // [])
| map(
select(
(.verbs // [])
| map(ascii_downcase)
| map(select(. == "bind" or . == "impersonate" or . == "escalate"))
| length > 0
)
)
| select(length > 0)
| "\($r.metadata.namespace)\t\($r.metadata.name)"
' | sort -u)
if [ -z "$suspect_roles" ]; then
echo "No Namespaced Roles with bind/impersonate/escalate verbs found."
else
echo "Roles with sensitive verbs (NAMESPACE,ROLE):"
printf ' %s\n' $suspect_roles
echo
echo "RoleBindings granting these Roles:"
kubectl get rolebindings --all-namespaces -o json \
| jq -r --argjson roles "$(printf '%s\n' "$suspect_roles" | jq -R . | jq -s .)" '
.items[]
| . as $rb
| select(.roleRef.kind == "Role")
| ($rb.metadata.namespace + "\t" + .roleRef.name) as $key
| $roles
| index($key) as $idx
| select($idx != null)
| $rb.metadata.name as $rbname
| .roleRef.name as $rolename
| $rb.metadata.namespace as $ns
| (.subjects // [])[]?
| "\($ns)\t\($rbname)\t\($rolename)\t\(.kind)\t\(.namespace // "-")\t\(.name)"
' | sort -u \
| awk 'BEGIN { OFS="\t"; print "NAMESPACE","RB_NAME","ROLE","SUBJECT_KIND","SUBJECT_NAMESPACE","SUBJECT_NAME" } 1'
fi
echo
echo "=== 4) Direct use of 'impersonate' verb in any Role/ClusterRole ==="
echo
echo "--- Raw summary (for deeper review) ---"
kubectl get clusterroles,roles --all-namespaces -o json \
| jq -r '
.items[]
| . as $obj
| ($obj.rules // [])
| map(
select(
(.verbs // [])
| map(ascii_downcase)
| index("impersonate") != null
)
)
| select(length > 0)
| "\($obj.kind)\t\($obj.metadata.namespace // "-")\t\($obj.metadata.name)"
' | sort -u \
| awk 'BEGIN { OFS="\t"; print "KIND","NAMESPACE","NAME_WITH_IMPERSONATE" } 1'
How to interpret the output
- Any
ClusterRoleorRolelisted in sections 1 or 4 usesbind,impersonate, orescalate. - Any binding listed in sections 2 and 3 shows who (users, groups, service accounts) receives those powerful permissions.
- Problematic cases are subjects that do not absolutely need these capabilities (for example, broad groups like
system:authenticated, CI/CD service accounts, or general application service accounts). - Use this report to decide, manually, where you can safely:
- Remove the binding, or
- Replace with a less-privileged role that omits
bind,impersonate, andescalate.