Safeguard
Security Guides•

Kubernetes securityContext checklist: the settings that matter

A copy-ready pod securityContext: non-root user, no privilege escalation, read-only root filesystem, dropped capabilities and RuntimeDefault seccomp.

Safeguard Security Team
3 min read

A hardened securityContext runs the container as a non-root user, disallows privilege escalation, mounts the root filesystem read-only, drops all Linux capabilities and uses the runtime's default seccomp profile. These settings line up with the Restricted Pod Security Standard, so they also help you pass admission checks.

Pod level versus container level

The securityContext under spec applies to all containers in the pod. A securityContext on a container applies to that container only, and per the Kubernetes docs it overrides the pod setting where both exist. Put user, group and seccomp at pod level, and the container-specific hardening at container level.

The checklist

Copy this and adjust the user IDs:

spec:
  securityContext:
    runAsUser: 1000
    runAsGroup: 3000
    runAsNonRoot: true
    fsGroup: 2000
    seccompProfile:
      type: RuntimeDefault
  containers:
  - name: app
    image: registry.example.com/app:1.4.2
    securityContext:
      allowPrivilegeEscalation: false
      readOnlyRootFilesystem: true
      privileged: false
      capabilities:
        drop: ["ALL"]

What each does:

  • runAsUser and runAsGroup: all container processes run with that UID and primary GID. The docs note that if runAsGroup is omitted, the primary group is root.
  • runAsNonRoot: the kubelet refuses to start a container that would run as UID 0.
  • fsGroup: adds a supplementary group to processes and sets group ownership on volumes.
  • allowPrivilegeEscalation: false: controls the no_new_privs flag. It defaults to true when unset, so you must set it.
  • readOnlyRootFilesystem: mounts the root filesystem read-only. Writable paths must come from volumes.
  • capabilities drop ALL: removes Linux capabilities. Add back only what the process needs, such as NET_BIND_SERVICE for ports below 1024.
  • seccompProfile RuntimeDefault: applies the container runtime's default filter.

Things that break and how to fix them

The app writes to its own directory. Mount an emptyDir at that path, or at tmp.

The app binds port 80. Move it to 8080, or add NET_BIND_SERVICE back.

Files are owned by root. Rebuild the image with a USER instruction and correct ownership, or set fsGroup for mounted volumes.

The docs warn that the user or group must have the permissions the application needs, and a mismatch causes file access failures.

Verify

Check the effective user in a running pod:

kubectl exec -it POD_NAME -- id

The output shows uid, gid and groups. Then check admission with Pod Security labels in warn mode, as covered in Pod Security admission rollout.

Safeguard policies and gates can check manifests in the pull request for these fields, so a missing setting is caught in review.

Rolling it out across many workloads

Do not edit fifty manifests by hand. Put the settings in a shared Helm values file or a kustomize base, and let each service override only what it must. Add a policy check in CI that fails when a manifest omits the fields, and list the exceptions in one place with owners and dates.

Quick check

Is runAsNonRoot enough on its own?

No. It does not stop privilege escalation or remove capabilities. Set the full list.

Do I need all of these in every pod?

Aim for yes. Document any exception, such as an added capability, with the reason.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.