03. Kubernetes SecurityContext & Pod Security Standards
Kubernetes securityContext parameters define privilege, isolation, and access control settings for Pods and individual Containers. Without explicit security context parameters, Kubernetes runs containers with default settings that permit privilege escalation, root execution, unmasked kernel capabilities, and arbitrary filesystem writes.
To protect workloads against container escapes and kernel exploitation, administrators must enforce the official Kubernetes Pod Security Standards (PSS) using the Pod Security Admission (PSA) controller.
1. Kubernetes Pod Security Standards (PSS) & Admission Controlsβ
Kubernetes categorizes pod security requirements into three progressive profiles:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β KUBERNETES POD SECURITY STANDARDS (PSS) β
ββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Profile β Description & Security Controls Enforced β
ββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β **Privileged**β Unrestricted. Allows host root access, host PID/NET/IPC, β
β β privileged mode, and custom capabilities. (Infrastructure only)β
ββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β **Baseline** β Minimal restrictions. Blocks known privilege escalation β
β β vectors, host network/PID namespaces, and host path mounts. β
ββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β **Restricted**β Production Hardened. Forces non-root execution, drops ALL β
β β Linux capabilities, restricts volume types, enforces Seccomp. β
ββββββββββββββββ΄βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Enforcing Pod Security Admission via Namespace Labelsβ
Enforce the Restricted Pod Security profile at the namespace boundary by setting namespace metadata labels:
apiVersion: v1
kind: Namespace
metadata:
name: production
labels:
# Enforces strict compliance; blocks non-compliant pod creation
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/enforce-version: latest
# Generates warnings in kubectl output for soft violations
pod-security.kubernetes.io/warn: restricted
pod-security.kubernetes.io/warn-version: latest
2. Technical Breakdown of securityContext Controlsβ
Security parameters can be applied at the Pod Level (applies to all containers in the Pod) or at the Container Level (overrides settings for a specific container).
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β SECURITYCONTEXT FIELD DEEP DIVE β
βββββββββββββββββββββββββββββββ¬βββββββ¬βββββββββββββββββββββββββββββββββββββββββ€
β Field Parameter β Levelβ Security Purpose β
βββββββββββββββββββββββββββββββΌβββββββΌβββββββββββββββββββββββββββββββββββββββββ€
β `runAsNonRoot: true` β Pod β Prevents container from starting if β
β β β configured to execute as UID 0 (root). β
βββββββββββββββββββββββββββββββΌβββββββΌβββββββββββββββββββββββββββββββββββββββββ€
β `runAsUser: 10001` β Pod β Explicitly assigns an unprivileged β
β `runAsGroup: 10001` β β User ID and Group ID to the process. β
βββββββββββββββββββββββββββββββΌβββββββΌβββββββββββββββββββββββββββββββββββββββββ€
β `allowPrivilegeEscalation` β Cont β Disables `setuid` and `setgid` binary β
β `: false` β β execution to prevent root escalation. β
βββββββββββββββββββββββββββββββΌβββββββΌβββββββββββββββββββββββββββββββββββββββββ€
β `readOnlyRootFilesystem` β Cont β Mounts container root filesystem as β
β `: true` β β read-only; blocks writing malware/logs.β
βββββββββββββββββββββββββββββββΌβββββββΌβββββββββββββββββββββββββββββββββββββββββ€
β `capabilities.drop: [ALL]` β Cont β Drops all 41 Linux kernel capabilities β
β β β from the container process header. β
βββββββββββββββββββββββββββββββΌβββββββΌβββββββββββββββββββββββββββββββββββββββββ€
β `seccompProfile.type` β Pod/ β Applies `RuntimeDefault` Seccomp filterβ
β `: RuntimeDefault` β Cont β to block ~44 dangerous system calls. β
βββββββββββββββββββββββββββββββ΄βββββββ΄βββββββββββββββββββββββββββββββββββββββββ
Critical Security Parameters Explained:β
1. allowPrivilegeEscalation: falseβ
Controls whether a process can gain more privileges than its parent process. Setting this to false sets the no_new_privs flag in the Linux kernel, preventing binaries with the setuid or setgid bit (e.g. sudo, su, chsh) from elevating privileges.
2. readOnlyRootFilesystem: trueβ
Prevents attackers who achieve Remote Code Execution (RCE) from modifying application source files, replacing binaries, installing rootkits, or writing scripts to disk.
[!TIP] Handling Temporary File Writes: If your application requires temporary directories like
/tmpor/var/log, mount an in-memoryemptyDirvolume instead of making the root filesystem writable.
3. capabilities.drop: ["ALL"]β
Completely strips all default Linux capabilities (CAP_NET_RAW, CAP_SYS_CHROOT, CAP_MKNOD, etc.). If a process strictly requires a specific capability (such as CAP_NET_BIND_SERVICE to bind to port 80), explicitly drop ALL first and add only the single required capability.
3. Custom Seccomp & AppArmor Profiles in Kubernetesβ
A. Custom Seccomp Profile Configurationβ
If the RuntimeDefault profile is too permissive for high-security workloads, create a custom JSON Seccomp profile on the node host:
{
"defaultAction": "SCMP_ACT_ERRNO",
"architectures": [
"SCMP_ARCH_X86_64",
"SCMP_ARCH_X86",
"SCMP_ARCH_AARCH64"
],
"syscalls": [
{
"names": [
"accept4",
"epoll_wait",
"exit_group",
"futex",
"read",
"write"
],
"action": "SCMP_ACT_ALLOW"
}
]
}
Reference the custom profile in the Pod spec:
securityContext:
seccompProfile:
type: Localhost
localhostProfile: profiles/strict-seccomp.json
4. Side-by-Side Manifest Comparisonβ
β Insecure Kubernetes Deployment Manifestβ
# INSECURE: Fails Restricted Pod Security Standard on multiple vectors!
apiVersion: apps/v1
kind: Deployment
metadata:
name: insecure-web-app
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: insecure-app
template:
metadata:
labels:
app: insecure-app
spec:
# VULNERABLE: Uses host namespaces!
hostPID: true
hostNetwork: true
containers:
- name: web-app
image: node:18
# VULNERABLE: Full privileged host access!
securityContext:
privileged: true
allowPrivilegeEscalation: true
readOnlyRootFilesystem: false
# VULNERABLE: Mounts host root disk and Docker socket!
volumeMounts:
- mountPath: /host-docker.sock
name: docker-socket
- mountPath: /host-root
name: host-fs
volumes:
- name: docker-socket
hostPath:
path: /var/run/docker.sock
- name: host-fs
hostPath:
path: /
β Production-Hardened Kubernetes Deployment Manifestβ
# SECURE: Fully compliant with Kubernetes Restricted Pod Security Standard
apiVersion: apps/v1
kind: Deployment
metadata:
name: hardened-web-app
namespace: production
labels:
app.kubernetes.io/name: web-app
app.kubernetes.io/component: backend
spec:
replicas: 3
selector:
matchLabels:
app: hardened-web-app
template:
metadata:
labels:
app: hardened-web-app
spec:
# 1. POD-LEVEL SECURITY CONTEXT
securityContext:
runAsNonRoot: true
runAsUser: 10001
runAsGroup: 10001
fsGroup: 10001
seccompProfile:
type: RuntimeDefault # Enforces Seccomp kernel syscall filtering
containers:
- name: web-app
image: myregistry.azurecr.io/appsec-atlas/api:v1.0.0
imagePullPolicy: Always
# 2. CONTAINER-LEVEL SECURITY CONTEXT
securityContext:
allowPrivilegeEscalation: false # Disables setuid binaries
readOnlyRootFilesystem: true # Blocks writing to container disk
capabilities:
drop:
- ALL # Drops ALL Linux kernel capabilities!
resources:
limits:
cpu: "500m"
memory: "512Mi"
requests:
cpu: "100m"
memory: "128Mi"
# 3. EPHEMERAL IN-MEMORY VOLUMES FOR TEMP WRITES
volumeMounts:
- mountPath: /tmp
name: tmp-volume
- mountPath: /var/log/app
name: log-volume
volumes:
- name: tmp-volume
emptyDir:
medium: Memory
sizeLimit: 64Mi
- name: log-volume
emptyDir:
medium: Memory
sizeLimit: 128Mi
Next Chapter: 04. NetworkPolicies & RBAC Hardening β