Minimize The Admission Of Containers With
More Info:
Containers with allowPrivilegeEscalation set to true can gain more privileges than their parent process. Their admission should be restricted via Pod Security Admission policies.
Risk Level
High
Address
Security
Compliance Standards
- CIS AKS
Triage and Remediation
- Remediation
Remediation
Manual Steps
-
Identify namespaces with user workloads and current Pod Security labels
- Run on: any machine with kubectl access
kubectl get ns --show-labels- Decide which namespaces are true “user workload” namespaces (exclude
kube-system,gatekeeper-system,aks-*, monitoring/logging system namespaces, etc.), and note if they already havepod-security.kubernetes.io/*labels.
-
Review current use of allowPrivilegeEscalation in those namespaces
- Run on: any machine with kubectl access
# List pods whose containers explicitly set allowPrivilegeEscalation to truefor ns in NAMESPACE1 NAMESPACE2 NAMESPACE3; doecho "=== $ns ==="kubectl get pods -n "$ns" -o json | \jq -r '.items[] |{pod: .metadata.name,containers: (([.spec.initContainers[]?] + [.spec.containers[]?]) |map(select(.securityContext.allowPrivilegeEscalation == true) |{name, allowPrivilegeEscalation: .securityContext.allowPrivilegeEscalation}))} |select(.containers | length > 0)'done- If
jqis unavailable, save pod specs and review manually:
kubectl get pods -n NAMESPACE -o yaml > pods-NAMESPACE.yaml# Search for allowPrivilegeEscalation: true in the file -
Decide which workloads legitimately require allowPrivilegeEscalation=true
- For each pod/container identified above, review with the owning application/team:
- Why is
allowPrivilegeEscalation: trueneeded? - Can the image or behavior be changed to work with
allowPrivilegeEscalation: false?
- Why is
- Classify each workload as:
- “Can be fixed to
allowPrivilegeEscalation: false” - “Requires exception and must run in a non-restricted namespace”
- “Can be fixed to
- For each pod/container identified above, review with the owning application/team:
-
Harden pod specs where escalation is not required
- For pods that do not truly need escalation, update their Deployment/StatefulSet/Job manifests to explicitly set:
securityContext:allowPrivilegeEscalation: false- Apply the manifest updates:
kubectl apply -f UPDATED-MANIFEST.yaml- Re-run step 2 for the affected namespaces to confirm that no pods retain
allowPrivilegeEscalation: trueexcept those intentionally exempt.
-
Apply Pod Security Admission labels to enforce restricted policy
- For user-workload namespaces where all (or all but explicit exception) workloads can comply, enforce
restrictedand enable warnings cluster-wide: - Run on: any machine with kubectl access
# Enable warnings for all namespaces at least at baselinekubectl label --overwrite ns --all pod-security.kubernetes.io/warn=baseline# Enforce restricted where appropriatekubectl label --overwrite ns NAMESPACE1 pod-security.kubernetes.io/enforce=restrictedkubectl label --overwrite ns NAMESPACE2 pod-security.kubernetes.io/enforce=restricted- For namespaces that must host non-compliant workloads, do NOT set
enforce=restricted; instead, consider isolating them and documenting the exception.
- For user-workload namespaces where all (or all but explicit exception) workloads can comply, enforce
-
Verify enforcement and ongoing compliance
- Attempt to create a test pod with
allowPrivilegeEscalation: truein an enforced namespace (it should be rejected):
cat <<'EOF' > test-ape-true.yamlapiVersion: v1kind: Podmetadata:name: test-ape-truespec:containers:- name: cimage: busyboxcommand: ["sh", "-c", "sleep 3600"]securityContext:allowPrivilegeEscalation: trueEOFkubectl apply -n NAMESPACE1 -f test-ape-true.yaml- Confirm the admission failure message references Pod Security
restrictedandallowPrivilegeEscalation. - Periodically repeat step 2 (or integrate into CI) to ensure no new workloads reintroduce
allowPrivilegeEscalation: truein restricted namespaces.
- Attempt to create a test pod with
Using kubectl
# 1) List all namespaces and their Pod Security Admission labels
# Run on: any machine with kubectl access
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
# Problem indication:
# - ENFORCE is <none>, empty, or not "restricted" in namespaces that host user workloads.
# - WARN is <none> or not at least "baseline" where you expect warnings.
# 2) Show detailed labels on a specific namespace (replace with the namespace under review)
kubectl get ns default -o yaml | sed -n '/labels:/,/^ [^ ]/p'
# Problem indication:
# - labels section missing, or pod-security.kubernetes.io/enforce not set to "restricted"
# in a user-workload namespace.
# - No pod-security.kubernetes.io/warn label if you expect warnings for policy violations.
# 3) Find pods that explicitly allow privilege escalation
kubectl get pods --all-namespaces -o json \
| jq '.items[]
| {ns: .metadata.namespace, pod: .metadata.name,
containers: ([.spec.containers[], (.spec.initContainers // [])[]?]
| map({name, allowPrivilegeEscalation: (.securityContext.allowPrivilegeEscalation // "unset")}))}'
# Problem indication:
# - Any container or initContainer with "allowPrivilegeEscalation": true
# - Lack of PSA enforcement labels in the same namespace (from step 1) suggests
# there is nothing preventing future similar pods.
# 4) Test how Pod Security Admission would treat a sample pod in a namespace
# (dry-run create with an explicitly privileged container)
cat <<'EOF' | kubectl apply -f - --dry-run=server -n default
apiVersion: v1
kind: Pod
metadata:
name: psa-ape-test
spec:
containers:
- name: c
image: busybox
command: ["sh", "-c", "sleep 3600"]
securityContext:
allowPrivilegeEscalation: true
EOF
# Problem indication:
# - If the namespace is properly enforcing "restricted", this dry-run should fail
# with an admission error referencing PodSecurity restricted level.
# - If it is accepted (exit code 0 and no admission error), the namespace does NOT
# currently block allowPrivilegeEscalation=true.
# 5) Check for existing Azure Policy / Gatekeeper constraints that might also govern this
kubectl get constrainttemplates,constraints --all-namespaces 2>/dev/null
# Problem indication:
# - No constraints related to allowPrivilegeEscalation when your organization expects
# centralized policy enforcement beyond Pod Security Admission.
Automation
#!/usr/bin/env bash
#
# Report pods that allow privilege escalation, and namespaces without
# Pod Security Admission 'restricted' enforcement.
#
# Requirements:
# - Run on any machine with kubectl access to the cluster
# - kubectl must be configured with appropriate permissions
set -euo pipefail
echo "=== 1) Namespaces and Pod Security Admission labels ==="
echo
kubectl get ns -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.metadata.labels.pod-security\.kubernetes\.io/enforce}{"\t"}{.metadata.labels.pod-security\.kubernetes\.io/warn}{"\n"}{end}' \
| awk 'BEGIN { OFS="\t"; print "NAMESPACE","ENFORCE_LABEL","WARN_LABEL" }1' \
| column -t
cat <<'EOF'
Interpretation:
- NAMESPACEs with ENFORCE_LABEL not set to "restricted" do NOT enforce the Restricted Pod Security level.
These namespaces are candidates where allowPrivilegeEscalation=true might still be admitted.
- WARN_LABEL set to "baseline" only emits warnings; it does NOT block pods.
EOF
echo "=== 2) Pods/containers with allowPrivilegeEscalation = true or unset (implicitly true) ==="
echo
# This lists *all* containers where allowPrivilegeEscalation is either explicitly true
# or not specified (which defaults to true).
kubectl get pods -A -o json | \
jq -r '
.items[]
| {
ns: .metadata.namespace,
pod: .metadata.name,
containers: (
([.spec.containers[]? | {name, ape: ( .securityContext.allowPrivilegeEscalation // "UNSET" )}] +
[.spec.initContainers[]? | {name, ape: ( .securityContext.allowPrivilegeEscalation // "UNSET" )}])
)
}
| select(.containers | length > 0)
| .containers[]
| select(.ape == true or .ape == "UNSET")
| "\(.ns)\t\(.pod)\t\(.name)\t\(.ape)"
' 2>/dev/null \
| awk 'BEGIN { OFS="\t"; print "NAMESPACE","POD","CONTAINER","allowPrivilegeEscalation" }1' \
| column -t
cat <<'EOF'
Interpretation:
- Rows where allowPrivilegeEscalation == "true":
Container explicitly allows privilege escalation; this is a policy violation candidate.
- Rows where allowPrivilegeEscalation == "UNSET":
The field is not set, which defaults to true in Kubernetes; these should be reviewed and
considered for explicit allowPrivilegeEscalation: false under a Restricted policy.
Problem indicators:
- User-workload namespaces WITHOUT pod-security.kubernetes.io/enforce=restricted.
- Any container (init or app) listed above with allowPrivilegeEscalation=true or UNSET
in namespaces where you intend to enforce Restricted Pod Security.
NOTE:
- This script is for review and triage; fixing workloads requires case-by-case changes
to pod specs/manifests and careful coordination with application owners.
EOF