Minimize Wildcard Use In Roles And ClusterRoles
More Info:
Wildcards in Roles and ClusterRoles grant unpredictable and often excessive permissions. Replace wildcards with explicit resources and verbs to enforce least privilege.
Risk Level
Critical
Address
Security
Compliance Standards
- CIS OKE
Triage and Remediation
- Remediation
Remediation
Manual Steps
-
List all Roles and ClusterRoles that use wildcards
- Run on: any machine with kubectl access
kubectl get clusterroles -o json | jq -r '.items[]| select(.rules[]? | (.verbs[]? == "*" or .resources[]? == "*" or .apiGroups[]? == "*"))| .metadata.name' | sort -ukubectl get roles --all-namespaces -o json | jq -r '.items[]| select(.rules[]? | (.verbs[]? == "*" or .resources[]? == "*" or .apiGroups[]? == "*"))| "\(.metadata.namespace)/\(.metadata.name)"' | sort -u -
Inspect each wildcarded Role/ClusterRole in detail
- For each name from step 1, view the full spec:
# ClusterRole examplekubectl get clusterrole <clusterrole-name> -o yaml# Role examplekubectl get role -n <namespace> <role-name> -o yaml- Record for each rule:
- Which fields use
*(verbs,resources,apiGroups,resourceNames,nonResourceURLs) - Which subjects are bound (via RoleBindings/ClusterRoleBindings).
- Which fields use
-
Determine intended access and justify or reject each wildcard
For each Role/ClusterRole:- Identify business/operational purpose (who/what uses it, for what tasks).
# Show bindings that use a ClusterRolekubectl get clusterrolebindings -o yaml | grep -A5 "name: <clusterrole-name>"# Show bindings that use a Rolekubectl get rolebindings --all-namespaces -o yaml | grep -A5 "name: <role-name>"
- With application owners / operators, decide for each wildcard:
- Is the role truly generic/admin (e.g.
cluster-admin) and intentionally broad? If yes, document the justification and leave as-is. - Otherwise, enumerate the specific resources and verbs actually needed.
- Is the role truly generic/admin (e.g.
- Identify business/operational purpose (who/what uses it, for what tasks).
-
Design least-privilege replacement rules (on paper or in a draft file)
For each wildcarded rule you plan to tighten:- Replace
verbs: ["*"]with an explicit list (e.g.["get","list","watch"]for read-only, or addcreate,update, etc. only if required). - Replace
resources: ["*"]with only required resources per API group (e.g.["pods","deployments","configmaps"]). - Replace
apiGroups: ["*"]with specific groups (e.g.["","apps","batch"]). - Save the revised spec to a file for review, e.g.:
kubectl get clusterrole <clusterrole-name> -o yaml > /tmp/<clusterrole-name>.yaml# edit /tmp/<clusterrole-name>.yaml to remove wildcards and set explicit verbs/resources/apiGroups
- Replace
-
Apply tightened Roles/ClusterRoles carefully and validate workloads
- After peer review/change control, apply the edited objects:
kubectl apply -f /tmp/<clusterrole-name>.yaml# or for a Rolekubectl apply -f /tmp/<namespace>-<role-name>.yaml
- Coordinate with owners to run smoke tests for affected users/service accounts to confirm required operations still succeed and no critical functionality broke.
- After peer review/change control, apply the edited objects:
-
Re-verify that wildcards are minimized
- Re-run the discovery from step 1 to confirm only justified wildcarded Roles/ClusterRoles remain:
kubectl get clusterroles -o json | jq -r '.items[]| select(.rules[]? | (.verbs[]? == "*" or .resources[]? == "*" or .apiGroups[]? == "*"))| .metadata.name' | sort -ukubectl get roles --all-namespaces -o json | jq -r '.items[]| select(.rules[]? | (.verbs[]? == "*" or .resources[]? == "*" or .apiGroups[]? == "*"))| "\(.metadata.namespace)/\(.metadata.name)"' | sort -u- For any remaining wildcard use, ensure there is a written justification (e.g. break-glass admin, temporary migration) and a plan/date to revisit if appropriate.
Using kubectl
# 1) List all ClusterRoles that contain any '*' wildcard
# Run on: any machine with kubectl access
kubectl get clusterroles -o json \
| jq -r '
.items[]
| select(
(.rules[]?.verbs[]? == "*" )
or (.rules[]?.resources[]? == "*" )
or (.rules[]?.apiGroups[]? == "*" )
or (.rules[]?.resourceNames[]? == "*" )
)
| .metadata.name
' | sort -u
Output to review:
- Any name listed here is a ClusterRole that uses at least one wildcard and must be reviewed.
# 2) Inspect a specific ClusterRole in detail
# Replace CLUSTERROLE_NAME with a name from the previous command
kubectl get clusterrole CLUSTERROLE_NAME -o yaml
What indicates a problem:
- In
.rules:verbs: ["*"]orverbs: - "*".resources: ["*"]orresources: - "*".apiGroups: ["*"]orapiGroups: - "*".resourceNames: ["*"]orresourceNames: - "*".
- Especially risky when combined, e.g.:
apiGroups: ["*"]andresources: ["*"]andverbs: ["*"](effectively full admin).- Wildcards on sensitive resources like
secrets,configmaps,roles,clusterroles,rolebindings,clusterrolebindings, orpods/exec.
You must decide, per ClusterRole:
- Which resources it actually needs.
- Which verbs are really required (e.g.
get,list,watchvscreate,update,patch,delete). - Whether wildcards can be replaced with explicit lists.
# 3) Find RoleBindings and ClusterRoleBindings that use a wildcard-heavy ClusterRole
# Replace CLUSTERROLE_NAME with the name under review
kubectl get clusterrolebindings -o wide \
| grep -E "(^NAME| CLUSTERROLE_NAME )"
kubectl get rolebindings --all-namespaces -o wide \
| grep -E "(^NAMESPACE| CLUSTERROLE_NAME )"
Output to review:
- Which subjects (users, groups, service accounts) are granted the wildcarded ClusterRole.
- Broader or more sensitive subjects (e.g.
system:serviceaccounts,system:authenticated, production namespaces) indicate higher risk and increase the urgency to reduce wildcard use.
# 4) Quick cluster-wide overview of any wildcard usage in Roles (namespaced)
kubectl get roles --all-namespaces -o json \
| jq -r '
.items[]
| select(
(.rules[]?.verbs[]? == "*" )
or (.rules[]?.resources[]? == "*" )
or (.rules[]?.apiGroups[]? == "*" )
or (.rules[]?.resourceNames[]? == "*" )
)
| "\(.metadata.namespace)/\(.metadata.name)"
' | sort -u
Output to review:
- Any
namespace/namelisted is a Role with wildcard usage; examine them with:kubectl get role -n NAMESPACE NAME -o yaml - The same indicators of problematic wildcards apply as for ClusterRoles.
Automation
#!/usr/bin/env bash
# Report Roles/ClusterRoles that use wildcards in rules.*
# Run on: any machine with kubectl access and current-context pointing at target cluster
set -euo pipefail
# You can change this to a specific namespace list if desired
NAMESPACE_SELECTOR="--all-namespaces"
echo "=== Checking ClusterRoles for wildcard usage ==="
kubectl get clusterroles -o json \
| jq -r '
.items[]
| {
kind,
name: .metadata.name,
rules: (
.rules[]
| select(
(.verbs[]? == "*" )
or (.resources[]? == "*" )
or (.apiGroups[]? == "*" )
or (.resourceNames[]? == "*" )
)
)
}
| select(.rules != null)
| "KIND: \(.kind)\nNAME: \(.name)\nOFFENDING_RULES:\n\(.rules | tojson)\n---"
'
echo
echo "=== Checking Namespaced Roles for wildcard usage ==="
kubectl get roles ${NAMESPACE_SELECTOR} -o json \
| jq -r '
.items[]
| {
kind,
name: .metadata.name,
namespace: .metadata.namespace,
rules: (
.rules[]
| select(
(.verbs[]? == "*" )
or (.resources[]? == "*" )
or (.apiGroups[]? == "*" )
or (.resourceNames[]? == "*" )
)
)
}
| select(.rules != null)
| "KIND: \(.kind)\nNAMESPACE: \(.namespace)\nNAME: \(.name)\nOFFENDING_RULES:\n\(.rules | tojson)\n---"
'
Explanation of output indicating a problem:
- Any block printed by this script (separated by
---) represents a Role or ClusterRole that uses at least one wildcard in:rules[].verbs(e.g.,"*"),rules[].resources(e.g.,"*"),rules[].apiGroups(e.g.,"*"),- or
rules[].resourceNames(e.g.,"*").
Each such occurrence should be manually reviewed to determine whether you can replace the wildcard with a specific list of verbs, resources, API groups, or resource names to better enforce least privilege.