Minimize The Admission Of Privileged Containers
More Info:
Do not generally permit containers to be run with the securityContext.privileged flag set to true.
Risk Level
Critical
Address
Security
Compliance Standards
- APRA CPS 234 (Australia)
- BSI C5 (Germany)
- Brazil LGPD
- CCPA / CPRA (California)
- CIS Critical Security Controls v8
- CIS OKE
- CMMC 2.0
- CSA Cloud Controls Matrix v4
- DPDPA
- Digital Operational Resilience Act (EU)
- Essential 8
- ISO/IEC 27017
- ISO/IEC 27018
- ISO/IEC 27701
- KSA PDPL
- MAS Technology Risk Management (Singapore)
- MITRE ATT&CK (Cloud)
- NIS2 Directive
- NIST SP 800-171
- NYDFS 23 NYCRR 500
- SWIFT Customer Security Controls Framework
- Sarbanes-Oxley IT General Controls
- UK NCSC Cyber Assessment Framework
Triage and Remediation
- Remediation
Remediation
Manual Steps
-
Identify namespaces running user workloads
- On any machine with kubectl access:
kubectl get ns
- Decide which namespaces are user/workload namespaces vs. system/platform namespaces (often exclude: kube-system, kube-public, kube-node-lease, monitoring/istio/linkerd/ingress if managed by platform teams).
- On any machine with kubectl access:
-
Review current Pod Security Admission labels per namespace
- On any machine with kubectl access:
kubectl get ns --show-labels
- For each user/workload namespace, note values of:
pod-security.kubernetes.io/enforcepod-security.kubernetes.io/warnpod-security.kubernetes.io/audit
- Determine whether
enforceis set to at leastbaseline(ideallyrestricted) according to your risk tolerance and application needs.
- On any machine with kubectl access:
-
Check for currently running privileged pods
- On any machine with kubectl access:
kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}{" "}{.metadata.name}{" "}{.spec.containers[*].name}{" "}{.spec.containers[*].securityContext.privileged}{"\n"}{end}' \| grep -E " true$" || echo "No explicitly privileged containers found"
- For any pod/container showing
true, evaluate whether privileged mode is truly required (e.g., low-level host access, CNI, CSI, node monitoring agents). Document justified exceptions and namespaces they run in.
- On any machine with kubectl access:
-
Decide PSA policy per namespace (risk vs. application compatibility)
- For each user/workload namespace, choose:
restrictedfor most namespaces (blocks privileged containers and other high-risk settings).baselineonly where privileged or near-privileged features might be needed and cannot be refactored quickly.
- For system namespaces that must allow privileged workloads (e.g., kube-system with CNI/CSI/daemonsets), you may decide to leave
enforceunset or set tobaselinewhile ensuring you understand the residual risk.
- For each user/workload namespace, choose:
-
Apply or adjust Pod Security Admission labels
- On any machine with kubectl access, for each user/workload namespace you decided should be restricted:
kubectl label --overwrite ns NAMESPACE pod-security.kubernetes.io/enforce=restricted
- Optionally, to enable cluster-wide warning at
baselinelevel while you migrate:kubectl label --overwrite ns --all pod-security.kubernetes.io/warn=baseline - For namespaces requiring a weaker policy (e.g., baseline):
kubectl label --overwrite ns NAMESPACE pod-security.kubernetes.io/enforce=baseline
- On any machine with kubectl access, for each user/workload namespace you decided should be restricted:
-
Verify enforcement and monitor for blocked privileged pods
- Confirm labels:
kubectl get ns --show-labels | grep pod-security.kubernetes.io/enforce
- Attempt (in a test namespace) to create a privileged pod to confirm it is rejected where
restrictedis enforced:cat <<'EOF' > /tmp/privileged-pod.yamlapiVersion: v1kind: Podmetadata:name: privileged-testnamespace: NAMESPACEspec:containers:- name: testimage: busyboxcommand: ["sh", "-c", "sleep 3600"]securityContext:privileged: trueEOFkubectl apply -f /tmp/privileged-pod.yaml - Ensure the API server denies this pod in namespaces with
pod-security.kubernetes.io/enforce=restricted. If it is admitted, revisit labels and your namespace classification.
- Confirm labels:
Using kubectl
# 1) List namespaces and their Pod Security Admission labels
# Run on: any machine with kubectl access
kubectl get ns --show-labels
What to look for (problem indicators)
- Namespaces that host user workloads and do not have any of these labels:
pod-security.kubernetes.io/enforcepod-security.kubernetes.io/warnpod-security.kubernetes.io/audit
- Namespaces where
pod-security.kubernetes.io/enforceis missing or set to a value weaker than desired (e.g.,privilegedorbaselinewhen your policy requiresrestricted).
# 2) Show PSA labels (if present) for each namespace in a more focused way
kubectl get ns -o custom-columns=NAME:.metadata.name,\
ENFORCE:.metadata.labels.pod-security\\.kubernetes\\.io/enforce,\
WARN:.metadata.labels.pod-security\\.kubernetes\\.io/warn,\
AUDIT:.metadata.labels.pod-security\\.kubernetes\\.io/audit
What to look for (problem indicators)
ENFORCEcolumn is<none>for namespaces where privileged pods should be blocked.ENFORCEis set toprivilegedorbaselinewhere your standard requiresrestricted.
# 3) Identify pods currently running with privileged containers
kubectl get pods --all-namespaces -o jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{range .spec.containers[*]}{.name}{"="}{.securityContext.privileged}{";"}{end}{"\n"}{end}' \
| grep -E 'true'
What to look for (problem indicators)
- Any line showing
=truefor containers in user namespaces indicates a privileged container is admitted. - If such pods exist in namespaces without
pod-security.kubernetes.io/enforce=restricted, that namespace likely needs tighter policy (subject to business/operational review).
# 4) Inspect detailed securityContext for a specific suspicious pod
# Replace NAMESPACE and POD_NAME with real values
kubectl get pod POD_NAME -n NAMESPACE -o yaml
What to look for (problem indicators)
Under spec.containers[].securityContext or spec.initContainers[].securityContext:
privileged: true- Patterns suggesting broad host access (e.g.,
hostPID: true,hostNetwork: true) that may justify enforcingrestrictedPSA for the namespace after review.
These commands only surface the current state. Deciding which namespaces should enforce restricted (or allow exceptions) requires human review of workload requirements and risk tolerance.
Automation
#!/usr/bin/env bash
# Run on: any machine with kubectl access and suitable RBAC
set -euo pipefail
echo "=== 1) Namespaces without Pod Security Admission 'enforce' label ==="
kubectl get ns -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.metadata.labels.pod-security\.kubernetes\.io/enforce}{"\n"}{end}' \
| awk 'BEGIN{print "NAMESPACE\tENFORCE_LABEL"} {print}' \
| column -t
echo
echo "Namespaces with an empty or missing ENFORCE_LABEL are candidates for review."
echo
echo "=== 2) Pods running privileged containers (cluster-wide) ==="
# Show all pods with any container (or initContainer) privileged=true
kubectl get pods --all-namespaces -o json \
| jq -r '
.items[]
| . as $pod
| ([
(.spec.containers[]? | select(.securityContext.privileged == true) | {type:"container", name:.name}),
(.spec.initContainers[]? | select(.securityContext.privileged == true) | {type:"initContainer", name:.name})
] // [])
| select(length > 0)
| .[] as $c
| "\($pod.metadata.namespace)\t\($pod.metadata.name)\t\($c.type)\t\($c.name)"
' 2>/dev/null \
| awk 'BEGIN{print "NAMESPACE\tPOD\tTYPE\tCONTAINER"} {print}' \
| column -t || echo "No privileged containers found or jq not installed."
echo
echo "Any line listed above indicates a privileged container that must be reviewed."
echo
echo "=== 3) Per-namespace privileged pod summary ==="
kubectl get pods --all-namespaces -o json \
| jq -r '
.items[]
| select(
([.spec.containers[]?.securityContext.privileged] + [.spec.initContainers[]?.securityContext.privileged])
| map(select(. == true))
| length > 0
)
| .metadata.namespace
' 2>/dev/null \
| sort | uniq -c \
| awk 'BEGIN{print "COUNT_PRIV_PODS\tNAMESPACE"} {print}' \
| column -t || echo "No privileged pods found or jq not installed."
echo
cat <<'EOF'
INTERPRETING RESULTS
--------------------
1) Namespace PSA enforce label:
- Problematic for user-workload namespaces if:
ENFORCE_LABEL is empty or missing
These namespaces are not enforcing a Pod Security level (e.g. 'restricted')
and may admit privileged pods unless other controls exist.
2) Privileged pods:
- Any row in section (2) is a potential issue. Each identified pod has
at least one container with securityContext.privileged=true and should
be reviewed for necessity and risk.
3) Namespace summary:
- Namespaces with COUNT_PRIV_PODS > 0 must be reviewed. Determine whether
privileged workloads are strictly necessary; if not, plan changes to
their manifests and/or apply appropriate PSA labels (e.g. enforce=restricted).
NOTE: This script only reports state. Deciding which namespaces should enforce
'restricted' and which privileged workloads (if any) are justified requires
manual review and coordination with application owners.
EOF