← Policy catalog
</> ValidatingAdmissionPolicy · Apache-2.0

May Run as Root

pod-run-as-nonroot

severityModerate resourcePods productKubernetes bundles2

With runAsNonRoot unset, the kubelet never rejects an image whose user is UID 0, so the pod silently runs as root and any compromise gains root file ownership and the full capability set.

Rejects unless

has(object.spec.securityContext) && has(object.spec.securityContext.runAsNonRoot) && object.spec.securityContext.runAsNonRoot == true

spec.securityContext.runAsNonRoot must be set to true. Container-level fields may be undefined/nil when this is true.

Remediation

Set the pod-level runAsNonRoot to true so the kubelet refuses to start any container whose image resolves to UID 0. Field: spec.securityContext.runAsNonRoot.

Applies to

  • pods · v1 · CREATE, UPDATE

Manifest

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
  name: pod-run-as-nonroot
  annotations:
    kubeapt.io/uuid: "3e12a1ed-4cb4-4d04-9fc4-75c9ca5af6cc"
    security.kubeapt.io/displayName: "May Run as Root"
    security.kubeapt.io/description: "With runAsNonRoot unset, the kubelet never rejects an image whose user is UID 0, so the pod silently runs as root and any compromise gains root file ownership and the full capability set."
    security.kubeapt.io/resource: "Pods"
    security.kubeapt.io/severity: "Moderate"
    security.kubeapt.io/remediation: "Set the pod-level runAsNonRoot to true so the kubelet refuses to start any container whose image resolves to UID 0. Field: spec.securityContext.runAsNonRoot."
    security.kubeapt.io/product: "Kubernetes"
spec:
  failurePolicy: Fail
  matchConstraints:
    resourceRules:
    - apiGroups:
      - ''
      apiVersions:
      - v1
      operations:
      - CREATE
      - UPDATE
      resources:
      - pods
  validations:
  - expression: |
      has(object.spec.securityContext) && has(object.spec.securityContext.runAsNonRoot) && object.spec.securityContext.runAsNonRoot == true
    message: |
      spec.securityContext.runAsNonRoot must be set to true. Container-level fields may be undefined/nil when this is true.

Save it as pod-run-as-nonroot.yaml — the commands below assume that name.

Validate with kubeapt

Check a workload against this one policy, before anything is installed on a cluster.

$ kubeapt validate -p ./pod-run-as-nonroot.yaml -r ./workload.yaml

Or without the file, from the published policy set — -r takes a directory too:

$ kubeapt policies download && kubeapt validate --policy-name pod-run-as-nonroot -r ./manifests

Or against every namespace in the cluster your kubeconfig points at:

$ kubeapt validate --policy-name pod-run-as-nonroot -A