KCSA — Pod Security Standards (PSS)

5 minute read

What Are Pod Security Standards?

Pod Security Standards (PSS) define three progressively restrictive security levels for pods. They replaced the now-removed PodSecurityPolicy (PSP) as the recommended way to enforce pod security in Kubernetes.

PSS is not an enforcement mechanism — it is a set of policies that define what a pod is or is not allowed to do. Enforcement is handled by Pod Security Admission (PSA).

Key Point: PSS defines the what. PSA defines the how.


The Evolution: PSP → PSS/PSA

Understanding the timeline is important for the KCSA exam:

Version Event
Kubernetes 1.0 – 1.20 PodSecurityPolicy (PSP) was the primary pod security mechanism
Kubernetes 1.21 PSP deprecated — PSS/PSA introduced as alpha
Kubernetes 1.23 PSA moved to beta (enabled by default)
Kubernetes 1.25 PSP removed — PSS/PSA is the standard

Why was PSP replaced?

  • PSP was difficult to configure — complex RBAC bindings required
  • PSP had confusing mutation and validation behavior
  • PSP was hard to audit — no easy way to see which policy applied to which pod
  • PSS/PSA provides a simpler, namespace-level approach

The Three PSS Levels

PSS defines exactly three security levels. There are no custom levels.

Level Description Use Case
Privileged No restrictions whatsoever System-level workloads (kube-system)
Baseline Prevents known privilege escalations Most general-purpose workloads
Restricted Hardened, follows all best practices Security-sensitive workloads

Think of these as a spectrum from most permissive to most restrictive:

Privileged ◄──────────────────────────► Restricted
(no restrictions)    (Baseline)    (fully hardened)

Real-World Analogy: Airport Security Levels

To make this concrete, think of airport security:

PSS Level Airport Analogy
Privileged VIP/diplomatic access — no screening at all, full access to all areas
Baseline Standard passenger screening — metal detector, bag X-ray, catches obvious threats
Restricted Enhanced security screening — full body scan, shoe removal, liquid restrictions, random pat-downs

Most travelers (workloads) go through standard screening (Baseline). Only diplomats (system pods) skip it entirely (Privileged). High-risk flights (sensitive workloads) get enhanced screening (Restricted).


What Each Level Restricts

This is the most important table for the KCSA exam. Know what each level allows and denies:

Control Privileged Baseline Restricted
hostNetwork ✅ Allowed ❌ Denied ❌ Denied
hostPID ✅ Allowed ❌ Denied ❌ Denied
hostIPC ✅ Allowed ❌ Denied ❌ Denied
privileged containers ✅ Allowed ❌ Denied ❌ Denied
Host ports ✅ Allowed ❌ Denied ❌ Denied
allowPrivilegeEscalation ✅ Allowed ✅ Allowed ❌ Must be false
runAsNonRoot ✅ Allowed ✅ Allowed ✅ Must be true
Capabilities (add) ✅ Any ⚠️ Limited set ❌ Only NET_BIND_SERVICE
Capabilities (drop ALL) Not required Not required ✅ Required
Seccomp profile ✅ Any ✅ Any ✅ Must be RuntimeDefault or Localhost
Volume types ✅ Any ✅ Any ⚠️ Limited (no hostPath)
runAsUser ✅ Any ✅ Any ❌ Cannot be 0 (root)

Exam Tip: The Baseline level blocks the most dangerous escalation paths (hostNetwork, hostPID, privileged). The Restricted level goes further by requiring non-root, read-only filesystems, and dropped capabilities.


Baseline Level — What It Blocks

The Baseline level is designed to prevent known privilege escalations while being easy to adopt. It blocks:

  • Host namespaces: hostNetwork, hostPID, hostIPC must be false or unset
  • Privileged mode: privileged must be false or unset
  • Dangerous capabilities: Only a specific allowlist is permitted:
    • AUDIT_WRITE, CHOWN, DAC_OVERRIDE, FOWNER, FSETID, KILL, MKNOD, NET_BIND_SERVICE, SETFCAP, SETGID, SETPCAP, SETUID, SYS_CHROOT
  • Host ports: Must not specify host ports
  • procMount: Must be Default (not Unmasked)
  • Seccomp: Unconfined profile is not explicitly forbidden at Baseline, but it is at Restricted

Restricted Level — Full Hardening

The Restricted level enforces all Baseline restrictions plus:

  • runAsNonRoot: Must be true (or runAsUser must be non-zero)
  • Drop ALL capabilities: Containers must drop ALL capabilities
  • Only NET_BIND_SERVICE: The only capability that can be added back
  • Seccomp: Must use RuntimeDefault or Localhost profile
  • allowPrivilegeEscalation: Must be false
  • Volume types: Only the following are allowed:
    • configMap, csi, downwardAPI, emptyDir, ephemeral, persistentVolumeClaim, projected, secret
    • No hostPath volumes

When to Use Each Level

Use this decision guide to select the right PSS level:

  1. Is it a system-level component (CNI plugin, logging agent, node daemon)?
    • → Use Privileged
    • These workloads need host access to function
  2. Is it a standard application workload with no special requirements?
    • → Use Baseline
    • Blocks the most dangerous escalation vectors
    • Easy to adopt — most apps work without changes
  3. Is it a security-sensitive workload (financial, healthcare, PII, multi-tenant)?
    • → Use Restricted
    • Follows all hardening best practices
    • May require some application changes (non-root user, read-only filesystem)
  4. Not sure?
    • → Start with Baseline in enforce mode and Restricted in warn mode
    • This blocks dangerous pods immediately while showing you what would break under Restricted

PSS Level Examples

Privileged Pod (kube-system)

A CNI plugin like Calico needs host network access:

apiVersion: v1
kind: Pod
metadata:
  name: calico-node
  namespace: kube-system
spec:
  hostNetwork: true    # ❌ Blocked by Baseline & Restricted
  hostPID: true        # ❌ Blocked by Baseline & Restricted
  containers:
  - name: calico-node
    image: calico/node:v3.26
    securityContext:
      privileged: true  # ❌ Blocked by Baseline & Restricted

This pod requires the Privileged level — it cannot run under Baseline or Restricted.

Baseline-Compliant Pod

A standard web application:

apiVersion: v1
kind: Pod
metadata:
  name: web-app
spec:
  containers:
  - name: nginx
    image: nginx:1.25
    ports:
    - containerPort: 80
    # No hostNetwork, hostPID, or privileged mode
    # Compliant with Baseline ✅

Restricted-Compliant Pod

A fully hardened application:

apiVersion: v1
kind: Pod
metadata:
  name: secure-app
spec:
  securityContext:
    runAsNonRoot: true
    seccompProfile:
      type: RuntimeDefault
  containers:
  - name: app
    image: myapp:1.0
    securityContext:
      allowPrivilegeEscalation: false
      readOnlyRootFilesystem: true
      capabilities:
        drop: ["ALL"]
    resources:
      limits:
        cpu: "500m"
        memory: "128Mi"

This pod meets all Restricted requirements ✅.


Common Misconceptions

Misconception Reality
“PSS replaces RBAC” No — PSS controls what pods can do, RBAC controls who can create pods
“You must use Restricted everywhere” No — use the level appropriate to the workload
“Baseline is insecure” No — Baseline blocks the most critical privilege escalations
“PSS is a CRD you install” No — PSS is built into Kubernetes (no installation needed)
“PSP and PSS can coexist” Only in 1.21-1.24 during migration; PSP is removed in 1.25

Key Takeaways for the Exam

  1. PSS defines three levels: Privileged (no restrictions), Baseline (blocks known escalations), Restricted (fully hardened).

  2. PSP was deprecated in 1.21 and removed in 1.25. PSS/PSA is the replacement.

  3. PSS is not an enforcement mechanism — it defines policy levels. PSA enforces them.

  4. Baseline blocks: hostNetwork, hostPID, hostIPC, privileged mode, dangerous capabilities.

  5. Restricted adds: runAsNonRoot, drop ALL capabilities, seccomp RuntimeDefault, no allowPrivilegeEscalation, limited volume types.

  6. The only capability allowed under Restricted is NET_BIND_SERVICE.

  7. Most workloads should target Baseline at minimum, with Restricted as the goal for sensitive environments.


Next: Pod Security Admission (PSA) — how to enforce PSS levels across your namespaces.

Updated: