Skip to main content

Avoid Use Of System Masters Group

More Info:​

The special group system:masters should not be used to grant permissions to any user or service account, except where strictly necessary (e.g. bootstrapping access prior to RBAC being fully available)

Risk Level​

High

Address​

Security

Compliance Standards​

  • CIS Kubernetes

Triage and Remediation​

Remediation​

Manual Steps
  1. List all subjects currently bound to system:masters

    • On any machine with kubectl access:
      kubectl get clusterrolebindings -o yaml | grep -A5 '\bcluster-admin\b'
      kubectl get clusterrolebindings -o yaml | grep -A5 'system:masters'
      kubectl get clusterrolebindings -o wide
    • Identify any ClusterRoleBinding where:
      • .roleRef.name is cluster-admin, and/or
      • Any subject has kind: User or kind: Group with name: system:masters.
  2. Inventory which concrete identities rely on system:masters

    • For each binding referencing system:masters (either as roleRef == cluster-admin or subject group name), capture full details:
      kubectl get clusterrolebinding <BINDING_NAME> -o yaml
    • Note which are:
      • Human users (e.g., corporate SSO groups, individual user names).
      • Service accounts (kind: ServiceAccount).
      • External identities mapped to system:masters via authentication (e.g., OIDC, client cert CN/O, cloud IAM).
  3. Review necessity of cluster‑wide superuser access for each subject

    • For each user/group/service account discovered:
      • Determine its actual operational purpose (admin, CI/CD, monitoring, break‑glass, etc.).
      • Confirm with owners whether:
        • Ongoing cluster-admin/system:masters level access is required, or
        • Access can be reduced to specific namespaces/verbs/resources, or
        • Access is only needed for rare break‑glass scenarios.
  4. Design replacement RBAC where full superuser is not strictly required

    • For subjects that do not need full system:masters/cluster-admin:
      • Identify the minimal ClusterRole/Role (existing or to be created) that matches required permissions.
      • Prepare corresponding RoleBinding/ClusterRoleBinding manifests that:
        • Bind the subject to that minimal role.
        • Do not reference the system:masters group and avoid unnecessary cluster-admin usage.
      • Save the manifests locally (e.g. restricted-access-<subject>.yaml) for change review/approval.
  5. Apply reduced‑privilege bindings, then remove system:masters membership

    • On any machine with kubectl access, for each subject you have redesigned access for:
      1. Apply the replacement binding(s):
        kubectl apply -f restricted-access-<subject>.yaml
      2. Remove the previous binding that relied on system:masters / cluster-admin (only after confirming new access works in a test):
        kubectl delete clusterrolebinding <OLD_BINDING_NAME>
      • For identities mapped to system:masters at the auth layer (e.g., client certs with O=system:masters, OIDC groups, cloud IAM bindings), coordinate with the identity/IAM team to:
        • Stop mapping those identities into system:masters.
        • Map them into the new, least‑privilege roles instead.
  6. Verify no users are effectively granted via system:masters

    • On any machine with kubectl access, confirm there are no bindings referencing system:masters or unintended cluster-admin grants:
      kubectl get clusterrolebindings -o yaml | grep -A5 'system:masters' || echo "No system:masters references found"
      kubectl get clusterrolebindings -o yaml | grep -A5 '\bcluster-admin\b'
    • Manually confirm that:
      • Any remaining cluster-admin binding is strictly necessary (e.g., a controlled break‑glass account).
      • No regular user, group, or service account is granted access via system:masters.
Using kubectl
# 1) List all ClusterRoleBindings referencing system:masters
# Run on: any machine with kubectl access
kubectl get clusterrolebindings -o json | \
jq -r '
.items[]
| select(
(.roleRef.kind=="ClusterRole" and .roleRef.name=="cluster-admin")
or (.subjects[]?.kind=="Group" and .subjects[]?.name=="system:masters")
)
| .metadata.name
'

Problem indication:

  • Any ClusterRoleBinding that:
    • Has roleRef.name: cluster-admin and a subject with name: system:masters, or
    • Has any subject with kind: Group and name: system:masters, means membership in system:masters gives full admin access.

# 2) Inspect each suspicious ClusterRoleBinding in detail
# Replace <crb-name> with each name from the previous command
kubectl get clusterrolebinding <crb-name> -o yaml

In the output, look for:

  • subjects entries like:
    • kind: Group with name: system:masters
    • Any identity provider group (e.g. from OIDC) that you know is mapped to system:masters
  • roleRef with name: cluster-admin or any highly privileged role.

If system:masters is present in subjects, or if you know an external group is mapped to system:masters, that binding is high risk and needs human review.


# 3) List all RoleBindings that reference system:masters (less common, but possible)
kubectl get rolebindings --all-namespaces -o json | \
jq -r '
.items[]
| select(.subjects[]? | .kind=="Group" and .name=="system:masters")
| "\(.metadata.namespace)/\(.metadata.name)"
'

Problem indication:

  • Any RoleBinding where a subject has kind: Group and name: system:masters is using this special group to grant namespace-scoped access and should be reviewed. Even if the Role is not cluster-admin, those subjects also inherit any cluster-wide privileges of system:masters.

# 4) Enumerate which Kubernetes users/groups are currently authenticated
# (from kubeconfig contexts; this does NOT show all possible IdP users)
kubectl config view --raw -o json | jq -r '
.users[]?.user
| {
username: (.username // "N/A"),
client-certificate: (.["client-certificate-data"] // "cert-ref"),
exec: .exec
}
'

Problem indication:

  • Any user identity that you know (from your IdP, certificates, or API server auth config) is mapped into the system:masters group is a candidate for review. kubectl cannot see that mapping; you must correlate with your authentication setup.

# 5) Verify post-review state (re-run focused query)
kubectl get clusterrolebindings -o json | \
jq -r '
.items[]
| select(.subjects[]? | .kind=="Group" and .name=="system:masters")
| .metadata.name
'

If this command prints no names, then no ClusterRoleBindings directly grant access to the system:masters group. If it still returns any names, those bindings still need human review and a decision on whether to keep or change them.

Automation
#!/usr/bin/env bash
#
# Report any bindings that grant cluster-admin or system:masters-equivalent
# privileges so they can be reviewed manually.
#
# Run on: any machine with kubectl access and current-context set to target cluster

set -euo pipefail

echo "=== Context ==="
kubectl config current-context
echo

echo "=== 1) ClusterRoleBindings referencing 'system:masters' group directly ==="
kubectl get clusterrolebindings -o jsonpath='{range .items[?(@.subjects)]}{.metadata.name}{"\n"}{range .subjects[*]} KIND={.kind} NAME={.name} API-GROUP={.apiGroup}{"\n"}{end}{"\n"}{end}' \
| awk 'NR==1{print} /system:masters/ || NR==1'

echo
echo "=== 2) RoleBindings referencing 'system:masters' group directly (all namespaces) ==="
kubectl get rolebindings --all-namespaces -o jsonpath='{range .items[?(@.subjects)]}{.metadata.namespace}{"/"}{.metadata.name}{"\n"}{range .subjects[*]} KIND={.kind} NAME={.name} API-GROUP={.apiGroup}{"\n"}{end}{"\n"}{end}' \
| awk 'NR==1{print} /system:masters/ || NR==1'

echo
echo "=== 3) ClusterRoleBindings granting 'cluster-admin' ==="
kubectl get clusterrolebindings -o jsonpath='{range .items[?(@.roleRef.name=="cluster-admin")]}{.metadata.name}{"\n"}{.roleRef.kind}{" "}{.roleRef.name}{"\n"}{range .subjects[*]} KIND={.kind} NAME={.name} NAMESPACE={.namespace} API-GROUP={.apiGroup}{"\n"}{end}{"\n"}{end}'

echo
echo "=== 4) RoleBindings granting 'cluster-admin' (all namespaces) ==="
kubectl get rolebindings --all-namespaces -o jsonpath='{range .items[?(@.roleRef.name=="cluster-admin")]}{.metadata.namespace}{"/"}{.metadata.name}{"\n"}{.roleRef.kind}{" "}{.roleRef.name}{"\n"}{range .subjects[*]} KIND={.kind} NAME={.name} NAMESPACE={.namespace} API-GROUP={.apiGroup}{"\n"}{end}{"\n"}{end}'

echo
echo "=== 5) Users in kubeconfig(s) that may map to high-privilege subjects ==="
echo "Current kubectl kubeconfig:"
kubectl config view --minify --raw

echo
echo "Note:"
echo "- PROBLEMATIC output is any subject of kind 'User' or 'ServiceAccount' whose NAME is 'system:masters' in sections 1 or 2."
echo "- Also review any 'User' or 'ServiceAccount' subjects bound to 'cluster-admin' (sections 3 and 4); these are not"
echo " automatically violations of this control, but often indicate over-privileged identities."
echo "- There is no safe automatic removal: for each flagged subject you must decide manually whether it is still needed,"
echo " and, if not, adjust or delete the corresponding RoleBinding/ClusterRoleBinding."

Interpreting the output

  • A definite problem for this specific control is any line in sections 1 or 2 where:
    • KIND=Group and NAME=system:masters
  • These bindings should be reviewed and, if not strictly required, updated to remove the system:masters group subject.

Additional Reading:​