← Policy catalog
</> ValidatingAdmissionPolicy · Apache-2.0

May Run as Root

container-run-as-nonroot

severityModerate resourceContainers productKubernetes bundles2

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

Rejects unless

object.spec.containers.all(c,
  variables.podNonRootTrue
  ? (!has(c.securityContext) || !has(c.securityContext.runAsNonRoot) || c.securityContext.runAsNonRoot == true)
  : (has(c.securityContext) && has(c.securityContext.runAsNonRoot) && c.securityContext.runAsNonRoot == true)
)

spec.containers[*].securityContext.runAsNonRoot must be set to true, unless the Pod-level spec.securityContext.runAsNonRoot is true—in which case it may be undefined or true.

Variables

podNonRootTrue

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

Remediation

Set runAsNonRoot to true on every container, or set it once at pod level and let the containers inherit it. Fields: spec.containers[*].securityContext.runAsNonRoot, spec.securityContext.runAsNonRoot.

Applies to

  • pods · v1 · CREATE, UPDATE

Manifest

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
  name: container-run-as-nonroot
  annotations:
    kubeapt.io/uuid: "fddcc7f4-e923-4268-b4f7-dc947b46d9bb"
    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 container silently runs as root and any compromise gains root file ownership and the full capability set."
    security.kubeapt.io/resource: "Containers"
    security.kubeapt.io/severity: "Moderate"
    security.kubeapt.io/remediation: "Set runAsNonRoot to true on every container, or set it once at pod level and let the containers inherit it. Fields: spec.containers[*].securityContext.runAsNonRoot, spec.securityContext.runAsNonRoot."
    security.kubeapt.io/product: "Kubernetes"
spec:
  failurePolicy: Fail
  matchConstraints:
    resourceRules:
    - apiGroups:
      - ''
      apiVersions:
      - v1
      operations:
      - CREATE
      - UPDATE
      resources:
      - pods
  variables:
  - name: podNonRootTrue
    expression: |
      has(object.spec.securityContext) && has(object.spec.securityContext.runAsNonRoot) && object.spec.securityContext.runAsNonRoot == true
  validations:
  - expression: |
      object.spec.containers.all(c,
        variables.podNonRootTrue
        ? (!has(c.securityContext) || !has(c.securityContext.runAsNonRoot) || c.securityContext.runAsNonRoot == true)
        : (has(c.securityContext) && has(c.securityContext.runAsNonRoot) && c.securityContext.runAsNonRoot == true)
      )
    message: "spec.containers[*].securityContext.runAsNonRoot must be set to true, unless the Pod-level spec.securityContext.runAsNonRoot is true\u2014in which case it may be undefined or true.\n"

Save it as container-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 ./container-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 container-run-as-nonroot -r ./manifests

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

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