Kubernetes securityContext Explained: Every Field and Its Safe Value

The Kubernetes securityContext says what a container may do on the node: which user it runs as and which powers of root it keeps. Most fields are unset by default, and an unset field often means the least safe value.

A manifest with a safe baseline, which most application pods can use as is:

apiVersion: v1
kind: Pod
metadata:
  name: app
spec:
  securityContext:              # pod level: applies to every container
    runAsNonRoot: true
    runAsUser: 10001
    runAsGroup: 10001
    fsGroup: 10001
    seccompProfile:
      type: RuntimeDefault
  containers:
    - name: app
      image: registry.example.com/app:1.4.2
      securityContext:          # container level: wins over pod level
        allowPrivilegeEscalation: false
        readOnlyRootFilesystem: true
        capabilities:
          drop: ["ALL"]

This matches the Restricted Pod Security Standard. An app that writes files needs an emptyDir mounted where it writes, because of readOnlyRootFilesystem.

Pod level and container level

Some fields exist in both places: runAsUser, runAsGroup, runAsNonRoot, seLinuxOptions, seccompProfile and appArmorProfile. The container value wins when both are set. fsGroup, fsGroupChangePolicy, supplementalGroups and sysctls exist only at pod level. privileged, allowPrivilegeEscalation, capabilities, procMount and readOnlyRootFilesystem exist only at container level.

Every field, its safe value and the rule behind it

FieldSafe valueWhat goes wrongRule
runAsNonRoottrueThe container may start as rootNon-root containers
runAsUser, runAsGroupNot 00 is rootNon-root containers
privilegedfalseEvery device of the nodePrivileged containers
allowPrivilegeEscalationfalsesetuid binaries can gain rootPrivileged containers
capabilitiesdrop ALL, add only NET_BIND_SERVICESYS_ADMIN and NET_RAW give root’s powersInsecure capabilities
seccompProfile.typeRuntimeDefault or LocalhostUnconfined allows every syscallSeccomp profile
appArmorProfile.typeRuntimeDefault or LocalhostUnconfined turns AppArmor offAppArmor
seLinuxOptionsUnset, or a container typeA custom user or role breaks SELinux isolationSELinux
procMountDefaultUnmasked shows kernel interfaces in /procprocMount
sysctlsOnly the safe listUnsafe ones change the node for every podSysctls
readOnlyRootFilesystemtrueAn attacker can write tools into the container–

Pod spec keys that matter as much

These live next to securityContext in the pod spec, and Pod Security Standards check them too:

KeySafe valueRule
hostNetwork, hostPID, hostIPCfalseHost namespaces
ports[].hostPortUnset or 0hostPort
volumes[].hostPathNot usedhostPath volumes
volumesEight allowed typesVolume types

Check it before deploy

Pod Security Admission enforces Baseline or Restricted per namespace with one label:

kubectl label namespace app pod-security.kubernetes.io/enforce=restricted

The Cloud (IaC) Security plugin for IntelliJ IDEA flags every rule in the tables while you edit the manifest. More on cluster setup: Kubernetes security best practices and the security guides.