Safeguard
Containers

Kubernetes Pod Security Context: A Practical Hardening Guide

The Kubernetes pod security context controls the privileges your containers run with. Here is how to configure it, and how it relates to the retired PodSecurityPolicy.

Karan Patel
Platform Engineer
6 min read

A Kubernetes pod security context is the block of settings in a pod or container spec that defines the privileges and access controls a workload runs with, and getting it right is the difference between a contained breach and a container escape that compromises the whole node. If a container is compromised, the pod security context is what decides whether the attacker is trapped inside an unprivileged process or handed a path to the host. This guide covers the fields that matter and how they fit with the newer Pod Security Admission model.

What the pod security context controls

You set a security context at two levels. The securityContext under spec applies to the whole pod; a securityContext under an individual container overrides it for that container. The fields that carry the most security weight are:

apiVersion: v1
kind: Pod
metadata:
  name: api
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
    fsGroup: 2000
    seccompProfile:
      type: RuntimeDefault
  containers:
    - name: api
      image: myregistry/api:1.4.2
      securityContext:
        allowPrivilegeEscalation: false
        readOnlyRootFilesystem: true
        capabilities:
          drop: ["ALL"]

Each of these lines removes a specific piece of attack surface. runAsNonRoot with a numeric runAsUser stops the container from running as UID 0, which is the single most impactful setting. allowPrivilegeEscalation: false blocks a process from gaining more privileges than its parent, closing the setuid-binary path. readOnlyRootFilesystem: true prevents an attacker from writing tools or modifying binaries inside the container. Dropping all Linux capabilities and adding back only what a workload truly needs follows least privilege at the kernel level. The seccompProfile set to RuntimeDefault restricts the syscalls the container can make.

The settings that should almost never appear

Two fields are red flags in most environments. privileged: true gives the container nearly all host capabilities and effectively removes the isolation boundary; it belongs only to a handful of infrastructure workloads that genuinely need it. hostNetwork, hostPID, and hostIPC share the host's namespaces with the container and should be treated with the same suspicion. Any manifest requesting these deserves a specific justification recorded in review.

From PodSecurityPolicy to Pod Security Admission

If you learned Kubernetes security a few years ago, you learned PodSecurityPolicy. It is gone. PodSecurityPolicy was deprecated in Kubernetes v1.21 and removed entirely in v1.25. Clusters on 1.25 or later have no PSP API at all, so any tutorial that tells you to write a PodSecurityPolicy resource is out of date.

The built-in replacement is Pod Security Admission (PSA), which enforces the Pod Security Standards. Instead of writing complex policy objects bound through RBAC, you label a namespace with one of three profiles:

apiVersion: v1
kind: Namespace
metadata:
  name: production
  labels:
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/warn: restricted
    pod-security.kubernetes.io/audit: restricted

The three profiles are privileged (no restrictions), baseline (blocks known privilege escalations while staying broadly compatible), and restricted (the hardened profile that requires non-root, dropped capabilities, and the other controls shown earlier). The enforce, warn, and audit modes let you roll out gradually: turn on warn first to see what would break, then flip to enforce once your workloads comply.

The relationship to the pod security context is direct. PSA does not set your security context for you; it rejects pods whose security context does not meet the profile. So the two work together: you write a compliant securityContext on the pod, and PSA enforces that every pod in the namespace has one.

When the built-in profiles are not enough

Pod Security Admission is deliberately coarse. It gives you three profiles and no customization beyond that. Teams that migrated off PodSecurityPolicy expecting the same fine-grained rules often find PSA too blunt, for example if they need to allow one specific capability that the restricted profile forbids.

For that, the ecosystem has moved to policy engines like Kyverno and Open Policy Agent Gatekeeper. These let you write custom admission policies as code, so you can enforce "restricted, but this one namespace may add NET_BIND_SERVICE" or "every image must come from our registry." They replace the flexibility PodSecurityPolicy offered while fitting the current policy-as-code model. If you are coming from the old Kubernetes pod security policies world, this is where that granularity now lives.

Verifying your workloads in practice

Writing a good security context is only half the job; you also need to confirm what actually deploys. Scan your manifests before they ship with a tool like kubesec or an IaC scanner, which will flag a missing runAsNonRoot or a stray privileged: true. Then verify at runtime, because a compliant manifest can still reference an image full of known vulnerabilities. The security context contains a breach; it does not prevent the vulnerable code from being there in the first place.

That is why container hardening pairs a tight security context with image scanning. A composition analysis pass on the image tells you which packages inside carry known CVEs, so you fix the vulnerable layer and constrain what a compromise can do. Platforms such as Safeguard scan container images for exactly those known vulnerabilities, complementing the runtime constraints your security context provides. For a broader container hardening walkthrough, the security academy has hands-on material.

FAQ

What is a pod security context in Kubernetes?

It is the set of privilege and access-control settings in a pod or container spec, covering things like whether the container runs as root, whether privilege escalation is allowed, which Linux capabilities it holds, and whether its root filesystem is writable. It defines the security boundary a workload runs inside.

Is PodSecurityPolicy still available?

No. PodSecurityPolicy was deprecated in Kubernetes v1.21 and removed in v1.25. Clusters on 1.25 or later use Pod Security Admission with the Pod Security Standards, or a policy engine like Kyverno or OPA Gatekeeper, instead.

What are the most important security context settings?

runAsNonRoot with a numeric runAsUser, allowPrivilegeEscalation: false, readOnlyRootFilesystem: true, dropping all capabilities and adding back only what is needed, and a RuntimeDefault seccomp profile. Avoid privileged: true and host namespace sharing unless a workload genuinely requires them.

How do the Pod Security Standards profiles work?

Pod Security Admission applies one of three profiles per namespace via labels: privileged, baseline, and restricted. It runs in enforce, warn, or audit mode, so you can preview violations with warn before enforcing the profile and rejecting non-compliant pods.

Never miss an update

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