Skip to main content

Minimize Access To Create Pods

More Info:

The ability to create pods in a namespace can provide a number of opportunities for privilege escalation, such as assigning privileged service accounts to these pods or mounting hostPaths with access to sensitive data (unless Pod Security Policies are implemented to restrict this access)

Risk Level

Low

Address

Security

Compliance Standards

  • APRA CPS 234 (Australia)
  • BSI C5 (Germany)
  • Brazil LGPD
  • CCPA / CPRA (California)
  • CIS AKS
  • CIS Critical Security Controls v8
  • CMMC 2.0
  • CSA Cloud Controls Matrix v4
  • DPDPA
  • Digital Operational Resilience Act (EU)
  • Essential 8
  • ISO/IEC 27017
  • ISO/IEC 27018
  • ISO/IEC 27701
  • KSA PDPL
  • MAS Technology Risk Management (Singapore)
  • MITRE ATT&CK (Cloud)
  • NIST SP 800-171
  • NYDFS 23 NYCRR 500
  • SWIFT Customer Security Controls Framework
  • Sarbanes-Oxley IT General Controls
  • UK NCSC Cyber Assessment Framework

Triage and Remediation

Remediation

Manual Steps
  1. List all Roles and ClusterRoles that can create pods

    • Run on: any machine with kubectl access
    # Roles (namespaced)
    kubectl get roles --all-namespaces -o json \
    | jq -r '
    .items[]
    | select(
    .rules[]
    | select((.resources // []) | index("pods"))
    | select((.verbs // []) | index("create"))
    )
    | "\(.metadata.namespace)\t\(.metadata.name)"
    ' | sort

    # ClusterRoles (cluster-wide)
    kubectl get clusterroles -o json \
    | jq -r '
    .items[]
    | select(
    .rules[]
    | select((.resources // []) | index("pods"))
    | select((.verbs // []) | index("create"))
    )
    | .metadata.name
    ' | sort
  2. Identify who is bound to these Roles/ClusterRoles

    • Run on: any machine with kubectl access
    # ClusterRoleBindings
    kubectl get clusterrolebindings -o wide

    # RoleBindings in all namespaces
    kubectl get rolebindings --all-namespaces -o wide
    • Manually correlate roleRef.name with the Roles/ClusterRoles from step 1 and note the subjects (users, groups, service accounts) receiving pod-create permissions.
  3. Evaluate business/technical necessity of each binding

    • For each subject-role pair identified:
      • Determine what workload or team uses it (via namespace, service account name, or label conventions).
      • Confirm whether that subject truly needs to create pods (e.g., operators, CI/CD systems) or only needs lower privileges (e.g., manage existing pods but not create new ones).
    • Document cases where pod creation is not strictly required.
  4. Remove or tighten unnecessary pod-create permissions

    • Run on: any machine with kubectl access
    • For a Role that should no longer be able to create pods, edit and remove create from verbs or the entire pods rule if not needed:
    kubectl edit role -n <namespace> <role-name>
    • For a ClusterRole:
    kubectl edit clusterrole <clusterrole-name>
    • In the opened editor, find rules like:
    - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "list", "watch", "create", "delete"]
    • Remove create (and delete if not required), then save:
    - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "list", "watch"]
  5. Re-scope overly broad bindings to least privilege

    • If a ClusterRole must retain pod-create for a narrow use case:
      • Prefer binding it only to specific service accounts instead of user/group wildcards.
      • Consider replacing a broad ClusterRole with a more restrictive Role in a specific namespace:
      # Example: create a namespaced Role with limited pod access
      kubectl create role pod-creator -n <namespace> \
      --verb=create --resource=pods

      # Bind it only to the intended service account
      kubectl create rolebinding pod-creator-binding -n <namespace> \
      --role=pod-creator \
      --serviceaccount=<namespace>:<service-account-name>
    • Remove or update old RoleBindings/ClusterRoleBindings that granted wider access than needed:
    kubectl delete rolebinding -n <namespace> <binding-name>
    kubectl delete clusterrolebinding <binding-name>
  6. Verify the reduced pod-create surface

    • Run on: any machine with kubectl access
    # Re-run evidence collection
    kubectl get roles --all-namespaces -o json \
    | jq -r '
    .items[]
    | select(
    .rules[]
    | select((.resources // []) | index("pods"))
    | select((.verbs // []) | index("create"))
    )
    | "\(.metadata.namespace)\t\(.metadata.name)"
    ' | sort

    kubectl get clusterroles -o json \
    | jq -r '
    .items[]
    | select(
    .rules[]
    | select((.resources // []) | index("pods"))
    | select((.verbs // []) | index("create"))
    )
    | .metadata.name
    ' | sort
    • Confirm that only justified roles/clusterroles retain create on pods and that their bindings are limited to the minimum necessary subjects.
Using kubectl
# 1) List all Roles that can create pods (any machine with kubectl access)
kubectl get roles -A -o json \
| jq -r '
.items[]
| select(
.rules[]
| (.verbs[]? | IN("create")) and
(.resources[]? | IN("pods"))
)
| [.metadata.namespace, .metadata.name] | @tsv
' | sort

Output indicates potential risk: any line is a Role (namespace and name) that grants pod creation. Each must be manually reviewed for necessity and scope.

# 2) Show full definitions of those Roles for review
# (replace <namespace> and <role> values from previous output)
kubectl get role -n <namespace> <role> -o yaml

Concerning patterns in rules:

  • verbs: ["*"] or includes create
  • resources: ["*"] or includes pods
  • Very broad apiGroups: ["*"]
# 3) List all ClusterRoles that can create pods
kubectl get clusterroles -o json \
| jq -r '
.items[]
| select(
.rules[]
| (.verbs[]? | IN("create")) and
(.resources[]? | IN("pods"))
)
| .metadata.name
' | sort

Any name in the output is a ClusterRole that can create pods anywhere in the cluster and must be reviewed.

# 4) Show full ClusterRole definitions for review
kubectl get clusterrole <clusterrole-name> -o yaml

Problematic indicators in rules are the same: verbs including create (or "*"), and resources including pods (or "*"), especially on generic or widely used roles.

# 5) See which subjects are bound to each risky Role / ClusterRole

# 5a) For a namespace Role
kubectl get rolebinding -n <namespace> -o wide
kubectl get rolebinding -n <namespace> -o yaml

# 5b) For a ClusterRole
kubectl get clusterrolebinding -o wide
kubectl get clusterrolebinding -o yaml

Concerning patterns in bindings:

  • subjects that are broad (e.g., kind: Group with many users, system:authenticated)
  • Bindings in many namespaces to the same powerful ClusterRole
  • ServiceAccounts that do not clearly need pod-creation but are bound to such roles.

These commands only surface the current state. Deciding whether to remove or narrow create on pods and adjusting bindings requires human review of each role’s actual use.

Automation
#!/usr/bin/env bash
#
# Report all Roles and ClusterRoles that can create pods,
# and which subjects (users/groups/serviceaccounts) are bound to them.
#
# Run on: any machine with kubectl access and appropriate RBAC to list roles/bindings.

set -euo pipefail

echo "=== ClusterRoles with 'create' on 'pods' and their ClusterRoleBindings ==="
echo

# 1) ClusterRoles with create on pods
kubectl get clusterroles -o json \
| jq -r '
.items[]
| select(
.rules[]
| select(
((.resources // []) | index("pods"))
and
((.verbs // []) | index("create"))
)
)
| .metadata.name
' | sort -u | while read -r cr; do
[[ -z "$cr" ]] && continue
echo "ClusterRole: ${cr}"
echo " Rules:"
kubectl get clusterrole "$cr" -o json \
| jq -r '
.rules[]
| select(
((.resources // []) | index("pods"))
and
((.verbs // []) | index("create"))
)
' | sed 's/^/ /'
echo " Bound via ClusterRoleBindings:"
kubectl get clusterrolebindings -o json \
| jq -r --arg CR "$cr" '
.items[]
| select(.roleRef.kind=="ClusterRole" and .roleRef.name==$CR)
| " CRB: \(.metadata.name)\n" +
( .subjects // [] | map(" subject: \(.kind) \(.namespace // "-")/\(.name)") | join("\n") )
' | sed 's/^/ /'
echo
done

echo
echo "=== Namespaced Roles with 'create' on 'pods' and their RoleBindings ==="
echo

# 2) Namespaced Roles with create on pods, per namespace
for ns in $(kubectl get ns -o jsonpath='{.items[*].metadata.name}' | tr ' ' '\n' | sort); do
echo "Namespace: ${ns}"
# Roles
roles_with_create_pods=$(kubectl get roles -n "$ns" -o json \
| jq -r '
.items[]
| select(
.rules[]
| select(
((.resources // []) | index("pods"))
and
((.verbs // []) | index("create"))
)
)
| .metadata.name
' | sort -u)

if [[ -z "${roles_with_create_pods}" ]]; then
echo " (no Roles with create on pods)"
echo
continue
fi

while read -r role; do
[[ -z "$role" ]] && continue
echo " Role: ${role}"
echo " Rules:"
kubectl get role "$role" -n "$ns" -o json \
| jq -r '
.rules[]
| select(
((.resources // []) | index("pods"))
and
((.verbs // []) | index("create"))
)
' | sed 's/^/ /'
echo " Bound via RoleBindings:"
kubectl get rolebindings -n "$ns" -o json \
| jq -r --arg ROLE "$role" '
.items[]
| select(.roleRef.kind=="Role" and .roleRef.name==$ROLE)
| " RB: \(.metadata.name)\n" +
( .subjects // [] | map(" subject: \(.kind) \(.namespace // "-")/\(.name)") | join("\n") )
' | sed 's/^/ /'
echo
done <<< "$roles_with_create_pods"
echo
done

Explanation of output indicating a problem:

  • Focus on Roles/ClusterRoles that:
    • Grant verbs including create on resources including pods.
  • Potentially problematic patterns to review manually:
    • Broad roles like * verbs or * resources that include pod creation.
    • Roles/ClusterRoles bound to:
      • system:authenticated, system:unauthenticated, or large user groups.
      • Service accounts in namespaces that should not be able to create pods.
      • Human users who don’t need pod-creation privileges.
  • For any such role/subject combination, decide whether:
    • Pod creation rights are truly required; if not, remove the binding or the rule.
    • Pod creation rights should be limited to a narrower set of service accounts or namespaces.

Use the names shown (Role/ClusterRole and RoleBinding/ClusterRoleBinding plus subjects) as inputs to manual review and RBAC edits (kubectl edit role, kubectl edit clusterrole, kubectl edit rolebinding, kubectl edit clusterrolebinding) following least privilege.