Minimize The Admission Of Privileged Containers
More Info:
Privileged containers run with elevated host capabilities and can compromise the underlying node. Use Pod Security Admission policies to restrict their admission.
Risk Level
Critical
Address
Security
Compliance Standards
- CIS EKS
Triage and Remediation
- Remediation
Remediation
Manual Steps
-
Identify namespaces with user workloads
Run on: any machine with kubectl accesskubectl get nsDecide which namespaces are user / application namespaces (exclude system namespaces like kube-system, kube-public, kube-node-lease, etc., unless you explicitly want PSA there).
-
Enforce
restrictedPod Security Admission on each user namespace
Run on: any machine with kubectl access
For each chosen namespace, run (replaceMY-NAMESPACEwith the actual name):kubectl label --overwrite ns MY-NAMESPACE pod-security.kubernetes.io/enforce=restrictedThis blocks creation of pods that request privileged containers in that namespace.
-
Optionally add warning-only policy cluster‑wide
Run on: any machine with kubectl access
This does not block pods, but surfaces warnings where they violate baseline:kubectl label --overwrite ns --all pod-security.kubernetes.io/warn=baseline -
Handle existing privileged pods (if any) by policy decision
Run on: any machine with kubectl access
List privileged pods:kubectl get pods --all-namespaces -o json | \jq -r '.items[] | select(any(.spec.containers[]?; .securityContext?.privileged == true)) |"\(.metadata.namespace) \(.metadata.name)"'For each listed pod:
- Decide if it is truly required; if not, delete it:
kubectl delete pod POD_NAME -n POD_NAMESPACE
- If required, plan a safer replacement (e.g., remove
privileged: trueand use more granular capabilities) and update the Deployment/DaemonSet/StatefulSet manifest that owns it.
- Decide if it is truly required; if not, delete it:
-
Recreate workloads with compliant securityContext
Run on: any machine with kubectl access
For each owning controller (Deployment/DaemonSet/StatefulSet, etc.) that used privileged containers, edit its manifest to removeprivileged: true, then apply:kubectl apply -f UPDATED-MANIFEST.yamlThe controller will recreate pods that comply with the
restrictedpolicy. -
Verification
Run on: any machine with kubectl accesskubectl get pods --all-namespaces -o json | \jq -r 'if any(.items[]?.spec.containers[]?; .securityContext?.privileged == true)then "PRIVILEGED_FOUND" else "NO_PRIVILEGED" end'Confirm the output is:
NO_PRIVILEGED
Using kubectl
# 1) Identify namespaces that host user workloads (adjust the label selector as needed)
# Run on: any machine with kubectl access
kubectl get ns --show-labels
# 2) Enforce RESTRICTED Pod Security Admission on specific user-workload namespaces
# Replace these namespace names with the actual ones in your cluster
# Run on: any machine with kubectl access
kubectl label --overwrite ns production \
pod-security.kubernetes.io/enforce=restricted
kubectl label --overwrite ns staging \
pod-security.kubernetes.io/enforce=restricted
kubectl label --overwrite ns development \
pod-security.kubernetes.io/enforce=restricted
# (Optional) For all current and future namespaces where you are comfortable
# with at least baseline restrictions, set a cluster-wide warning level
kubectl label --overwrite ns --all \
pod-security.kubernetes.io/warn=baseline
# 3) Verify: no privileged containers are currently running
# Run on: any machine with kubectl access
kubectl get pods --all-namespaces -o json | \
jq -r 'if any(.items[]?.spec.containers[]?; .securityContext?.privileged == true) then "PRIVILEGED_FOUND" else "NO_PRIVILEGED" end'
Automation
#!/usr/bin/env bash
#
# Enforce Pod Security Admission (PSA) restricted policy on all user namespaces
# and verify that no privileged containers are running.
#
# Requirements:
# - Run on any machine with kubectl access to the cluster.
# - kubectl and jq must be installed and configured.
#
# Idempotent: safe to re-run; labels are applied with --overwrite.
set -euo pipefail
########################
# Configuration
########################
# System / control-plane namespaces to EXCLUDE from "enforce=restricted".
# Adjust only if you knowingly run system components elsewhere.
EXCLUDE_NAMESPACES=(
"kube-system"
"kube-node-lease"
"kube-public"
"kube-fed-system"
"kubernetes-dashboard"
"local-path-storage"
"tigera-operator"
"calico-system"
"cilium-system"
)
########################
# Helper Functions
########################
is_excluded_ns() {
local ns="$1"
for e in "${EXCLUDE_NAMESPACES[@]}"; do
if [[ "$ns" == "$e" ]]; then
return 0
fi
done
return 1
}
########################
# Step 1: Enforce "restricted" on user namespaces
########################
echo "[INFO] Applying pod-security.kubernetes.io/enforce=restricted to user namespaces..."
# Get all namespaces
ALL_NS=$(kubectl get ns -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}')
for ns in $ALL_NS; do
if is_excluded_ns "$ns"; then
echo "[INFO] Skipping system namespace: $ns"
continue
fi
echo "[INFO] Labeling namespace '$ns' with enforce=restricted"
kubectl label --overwrite ns "$ns" pod-security.kubernetes.io/enforce=restricted=restricted
done
########################
# Step 2: Optionally warn baseline on all namespaces
########################
echo "[INFO] Ensuring pod-security.kubernetes.io/warn=baseline on all namespaces..."
kubectl label --overwrite ns --all pod-security.kubernetes.io/warn=baseline=baseline
########################
# Step 3: Verification
########################
echo "[INFO] Verifying that no privileged containers are currently running..."
RESULT=$(kubectl get pods --all-namespaces -o json | \
jq -r 'if any(.items[]?.spec.containers[]?; .securityContext?.privileged == true) then "PRIVILEGED_FOUND" else "NO_PRIVILEGED" end')
if [[ "$RESULT" == "NO_PRIVILEGED" ]]; then
echo "[PASS] Verification succeeded: NO_PRIVILEGED"
exit 0
else
echo "[WARN] Verification found privileged containers: PRIVILEGED_FOUND"
echo " Review and remediate privileged pods before re-running this script."
exit 1
fi