Skip to main content

More Info:

Do not generally permit containers to be run as the root user.

Risk Level

Critical

Address

Security

Compliance Standards

  • CIS Kubernetes

Triage and Remediation

Remediation

Manual Steps

  1. On any machine with kubectl access, list all namespaces and identify those that should strongly forbid root containers (typically all except system namespaces):
    Decide which namespaces must enforce non-root (e.g., all except: kube-system, kube-public, kube-node-lease, default if needed for legacy workloads).
  2. For each target namespace, inspect existing Pod Security/Admission policy mechanisms to see whether they already prevent root containers:
    Review whether any mechanism enforces runAsNonRoot: true or runAsUser ranges that exclude UID 0.
  3. For each policy mechanism in use, examine the detailed rules to confirm they require non-root UIDs:
    Verify that they enforce either MustRunAsNonRoot (or equivalent runAsNonRoot: true) or MustRunAs with UID ranges that do not include 0 for containers and pods in the target namespaces.
  4. Where no such enforcement exists for a target namespace, design or update a namespace‑scoped policy to require non‑root containers, using the mechanism your cluster supports. For example, with PodSecurityPolicy still enabled, you might define a PSP that contains:
    or:
    Then bind this policy (or the equivalent Gatekeeper/Kyverno policy) so that it applies to all service accounts in the target namespace.
  5. Before enforcing the new or updated policy, audit existing workloads in each namespace to find pods or workloads that currently run as root and would be blocked:
    For any listed workloads, review their manifests and application requirements; update them to run as a non‑root UID or formally document and justify an exception.
  6. After updating policies and workloads, verify that the policies are active and effective:
    • Confirm the policy objects and their bindings/assignments:
    • Attempt to deploy a simple pod that runs as root into a target namespace; it should be rejected by admission control. For example:
      Confirm that this creation fails and the error message indicates the non‑root requirement from your policy.

Using kubectl

1. List all namespaces (scope of review)

Run on: any machine with kubectl access.
You will need to review each namespace listed.

2. Check PodSecurityPolicies (if PSP is enabled)

For each PSP, inspect the allowed runAsUser strategies:
Look under .spec.runAsUser:
  • Compliant examples:
    • rule: MustRunAsNonRoot
    • rule: MustRunAs with ranges where all min/max are > 0 (no range including UID 0).
  • Problematic indicators:
    • rule: RunAsAny
    • rule: MustRunAs with any range including 0 (for example min: 0 or max: 0 or a range spanning 0).
Also check how PSPs are bound to namespaces via RBAC:
A problem exists where a namespace’s service accounts can use a PSP that allows RunAsAny or UID 0.

3. Check Pod Security Standards labels on namespaces (if used)

Look for labels like pod-security.kubernetes.io/enforce, pod-security.kubernetes.io/audit, pod-security.kubernetes.io/warn.
  • Compliant indicators:
    • Namespaces used for general workloads have enforce set to baseline or restricted.
    • For stronger guarantees against root containers, restricted is preferred.
  • Problematic indicators:
    • Missing pod-security.kubernetes.io/enforce label on application namespaces.
    • enforce=privileged or no label at all, combined with no other admission mechanism controlling user IDs.
Labels alone do not guarantee non-root; they must be interpreted with the Pod Security Standards definition. Namespaces without any restrictive labels need closer manual review.

4. Inspect common policy controllers (Kyverno, Gatekeeper) for runAsUser rules

If you use Kyverno:
If you use Gatekeeper:
Review any policies/constraints that reference runAsUser, runAsNonRoot, or Pod security context:
  • Compliant indicators:
    • Policies that deny pods where securityContext.runAsNonRoot=false or runAsUser=0.
    • Policies that require runAsNonRoot=true or runAsUser within non-zero ranges.
  • Problematic indicators:
    • No policies referencing runAsUser or runAsNonRoot.
    • Policies scoped only to a subset of namespaces, leaving important namespaces without protection.

5. Spot-check workloads in each namespace for actual root usage

This cannot replace policy, but helps you see current behavior.List all pods in a namespace:
Inspect a pod spec:
Look at:
  • .spec.securityContext.runAsUser
  • .spec.securityContext.runAsNonRoot
  • .spec.containers[*].securityContext.runAsUser
  • .spec.containers[*].securityContext.runAsNonRoot
Problematic indicators:
  • runAsUser: 0 anywhere.
  • runAsNonRoot: false.
  • No runAsUser/runAsNonRoot at pod or container level, and you know there is no enforced policy at namespace/cluster level (from steps 2–4); in that case, root containers are possible and not prevented by admission control.
Because this check is MANUAL, you must decide, based on the policy mechanisms (PSP, PSS labels, Kyverno/Gatekeeper, or others) and the namespaces’ purpose, whether:
  • The namespace has an admission policy that effectively enforces MustRunAsNonRoot or MustRunAs with UID ranges excluding 0, or
  • It is currently allowing root containers and needs a stricter policy.
Output indicating a problem (requires review/decision):
  • PodSecurity Admission:
    • Namespaces with ENFORCE of privileged or - (unset).
  • PodSecurityPolicy:
    • PSP lines ending with YES (RunAsAny/UNSET allows root) or
      YES (MustRunAs ranges include UID 0) or REVIEW (unknown rule).
  • Namespace defaults:
    • Any annotation (if present) that sets a default UID of 0 or otherwise includes 0.
  • Existing Pods:
    • Any row in the “Sample of running Pods that are effectively root (UID 0)” table.

Additional Reading: