Pod Security Standards: A Practical Kubernetes Guide
Published August 11, 2026 · 10 min read
Pod Security Standards are Kubernetes' built-in answer to a simple question: what is a pod allowed to ask for? They replaced the removed PodSecurityPolicy with three clear profiles and a namespace-label enforcement model that takes minutes to apply. This guide covers the profiles, how Pod Security Admission enforces them, a Restricted-compliant pod you can copy, and where the model stops.
The three profiles
The Pod Security Standards define three profiles, from most permissive to most locked down. Each is a fixed set of rules maintained by the Kubernetes project, so you are adopting a shared definition rather than inventing your own.
| Profile | Intent | Typical use |
|---|---|---|
| Privileged | Unrestricted; allows known privilege escalation | Trusted infra / system components only |
| Baseline | Blocks known privilege escalations; broadly compatible | A safe minimum for general workloads |
| Restricted | Current pod-hardening best practices | Production application workloads |
Baseline exists to catch the obviously dangerous — privileged containers, host namespaces, host-path mounts, extra capabilities — without breaking normal apps. Restricted goes further and encodes the hardening you actually want in production.
From PodSecurityPolicy to Pod Security Admission
If you remember PodSecurityPolicy(PSP), the profiles above are its spiritual successor. PSP was powerful but notoriously hard to get right — ordering was confusing, it could mutate pods, and a misconfigured policy could block every workload in a cluster. It was deprecated in Kubernetes 1.21 and removed in 1.25. Its replacement, Pod Security Admission(PSA), is a built-in admission controller that became stable in 1.25 and is enabled by default. PSA deliberately trades PSP's flexibility for simplicity: it does not mutate pods, and it enforces one of the three standard profiles per namespace rather than arbitrary custom rules.
Enforcing with namespace labels
PSA is configured entirely through namespace labels. Each of three modes — enforce, warn, and audit — takes one of the three profile levels. enforce rejects violating pods at admission; warn returns a message to whoever applied the manifest; audit records a violation in the audit log without blocking.
apiVersion: v1
kind: Namespace
metadata:
name: app
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/enforce-version: v1.31
pod-security.kubernetes.io/warn: restricted
pod-security.kubernetes.io/audit: restrictedOr apply it to an existing namespace directly: kubectl label ns app pod-security.kubernetes.io/enforce=restricted. The optional -version suffix pins the ruleset to a Kubernetes minor version so a cluster upgrade cannot silently tighten what your pods must satisfy.
A Restricted-compliant pod
Here is a pod that satisfies the Restricted profile. The key fields are runAsNonRoot, allowPrivilegeEscalation: false, dropping all capabilities, and a RuntimeDefault seccomp profile.
apiVersion: v1
kind: Pod
metadata:
name: hardened
namespace: app
spec:
securityContext:
runAsNonRoot: true
runAsUser: 10001
seccompProfile:
type: RuntimeDefault
containers:
- name: app
image: myapp:1.4.2
securityContext:
allowPrivilegeEscalation: false
privileged: false
readOnlyRootFilesystem: true # not required by Restricted, but recommended
capabilities:
drop: ["ALL"]
# add: ["NET_BIND_SERVICE"] # only if you must bind a port < 1024Use a numeric runAsUser so the kubelet can verify the container is non-root — it cannot resolve a username from the image at admission time. These runtime settings mirror the image-side hardening in our container image security checklist.
Baseline vs Restricted: what actually differs
The jump most teams feel is Baseline to Restricted, so it is worth being precise about what each one checks. Baseline blocks the well-known foot-guns while staying compatible with most existing manifests: no privileged containers, no host namespaces (hostNetwork, hostPID, hostIPC), no host-path volumes or host ports, no adding capabilities beyond a small default set, and no unsafe sysctls. Crucially, a plain pod with no security context at all usually passes Baseline — that is what makes it a safe floor.
Restricted is where pods must opt in explicitly. On top of everything Baseline forbids, it requires you to set runAsNonRoot: true, allowPrivilegeEscalation: false, a seccomp profile of RuntimeDefault or Localhost, all capabilities dropped (only NET_BIND_SERVICEmay be re-added), and restricted volume types. Because those fields are usually absent by default, an existing workload that sailed through Baseline will typically fail Restricted until you add the security context — which is exactly why you roll it out in stages rather than flipping the switch blind.
Rolling it out safely
Do not jump straight to enforce: restricted on a live namespace — you will reject deployments and generate a bad afternoon. Roll out in stages:
- Observe first. Set
warnandaudittorestrictedwhile leaving enforce at baseline or unset. You get the full list of violations without breaking anything. - Fix the workloads. Add the security context above to each Deployment until the warnings stop.
- Then enforce. Flip
enforceto restricted once the namespace is clean, and pin the version so upgrades are predictable. - Keep infra separate.System components that genuinely need privileges belong in their own namespaces labeled Privileged or Baseline — do not weaken a whole cluster to accommodate one agent.
Where Pod Security Admission stops
PSA is deliberately simple, and that simplicity is also its ceiling. It works at namespace granularity, cannot mutate pods to fix them, and only understands the three built-in profiles — you cannot express “Restricted, but also require images from our registry” or “allow this one extra capability for this one workload.” When you need policy that specific, reach for a general policy engine like Kyverno or OPA Gatekeeper, which can validate, mutate, and generate resources against custom rules. That is also how teams gate on image provenance and scan status at admission — covered in Kubernetes admission control for image scanning. PSA and a policy engine coexist happily: use PSA for the baseline everywhere, and a policy engine for the rules PSA cannot express.
Where ScanRook fits
Pod Security Standards constrain how a pod runs; they say nothing about whatis inside its image. A perfectly Restricted-compliant pod — non-root, no privilege escalation, all capabilities dropped — can still be running an image with a critical OpenSSL or glibc CVE, and PSA will happily admit it. The two controls answer different questions and belong together: PSA limits the blast radius if a workload is compromised, and image scanning reduces the chance of a compromise by catching the vulnerable software before it ships. ScanRook covers the image side, unpacking each layer and matching every package against OSV, NVD, and vendor advisory data. Wire a scan into CI and enforce Restricted in the cluster, and you have both halves. The image gate is detailed in our Kubernetes vulnerability scanning guide.
Frequently asked questions
What are the Pod Security Standards?
Three Kubernetes-maintained profiles — Privileged, Baseline, and Restricted — that define what a pod is allowed to request, from unrestricted to fully hardened.
What replaced PodSecurityPolicy?
Pod Security Admission, a built-in controller stable since Kubernetes 1.25. PSP was deprecated in 1.21 and removed in 1.25.
How do I enforce a profile?
Label the namespace with pod-security.kubernetes.io/enforce set to baseline or restricted, optionally adding warn and audit at the same or a stricter level.
Does it check the image?
No. PSS governs runtime privileges, not image contents. A Restricted pod can still run a vulnerable image, so pair it with scanning.
Restricted pods, scanned images
Enforce Restricted to constrain the runtime, and scan images so a hardened pod is not running vulnerable software. ScanRook unpacks every layer and matches each package against multiple advisory sources, with the source shown per finding.