Skip to main content

Minimize The Admission Of Containers With Allow Privilege

More Info:

Do not generally permit containers to be run with the allowPrivilegeEscalation flag set to true.

Risk Level

High

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)
  • 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

Manual Steps
  1. List namespaces with user workloads and existing policies

    • Run on: any machine with kubectl access
    kubectl get ns
    kubectl get psp,pss,validatingwebhookconfiguration,mutatingwebhookconfiguration -A 2>/dev/null
    • Decide which namespaces contain user workloads (exclude system namespaces such as kube-system, kube-public, kube-node-lease, provider-specific system namespaces, etc.).
  2. Review current constraints on allowPrivilegeEscalation per namespace

    • For each user namespace <ns>:
    # Check if any PodSecurity admission labels are present
    kubectl get ns <ns> -o yaml | grep -i "pod-security" -A2 || true

    # List pods and containers that currently use allowPrivilegeEscalation=true
    kubectl get pods -n <ns> -o json | \
    jq -r '
    .items[]
    | {pod: .metadata.name,
    c: (.spec.containers + (.spec.initContainers // []))}
    | .pod as $pod
    | .c[]
    | select(.securityContext.allowPrivilegeEscalation == true)
    | "\($pod) \(.name) allowPrivilegeEscalation=true"
    '
    • Note namespaces/workloads that require privileged behavior and those that do not.
  3. Decide your policy per namespace

    • For each user namespace, choose one of:
      • Strict: disallow allowPrivilegeEscalation=true for all user workloads.
      • Exception-based: disallow by default but allow for a small set of known pods/containers after review.
    • Document any workloads that must keep allowPrivilegeEscalation=true and why (e.g., specific debug/infra containers).
  4. Implement or adjust admission policy for each namespace

    • Option A – using Pod Security admission labels (per namespace <ns>):
      • To enforce at least restricted (which effectively disallows allowPrivilegeEscalation=true except for system workloads in exempt namespaces):
        kubectl label ns <ns> \
        pod-security.kubernetes.io/enforce=restricted \
        pod-security.kubernetes.io/enforce-version=latest \
        --overwrite
    • Option B – using a validating admission policy/mechanism you already run (e.g., Gatekeeper/Kyverno/ValidatingAdmissionPolicy):
      • Create or adjust a policy that rejects pods where any container or initContainer has securityContext.allowPrivilegeEscalation=true in the target namespaces.
      • Apply via your existing policy deployment manifests, then verify with a dry-run pod (see next step).
  5. Test that the policy behaves as intended

    • On any machine with kubectl access, for each protected namespace <ns>:
    cat <<'EOF' | kubectl apply -n <ns> -f - --dry-run=server
    apiVersion: v1
    kind: Pod
    metadata:
    name: test-allow-pe-true
    spec:
    containers:
    - name: c
    image: busybox
    command: ["sh", "-c", "sleep 3600"]
    securityContext:
    allowPrivilegeEscalation: true
    EOF
    • Confirm this is rejected in namespaces where you decided to disallow allowPrivilegeEscalation=true.
    • Optionally test a pod omitting allowPrivilegeEscalation or setting it to false to confirm legitimate workloads still admit.
  6. Re-verify cluster-wide and track exceptions

    • Run on any machine with kubectl access:
    # Re-scan all namespaces for pods with allowPrivilegeEscalation=true
    for ns in $(kubectl get ns -o jsonpath='{.items[*].metadata.name}'); do
    echo "Namespace: $ns"
    kubectl get pods -n "$ns" -o json | \
    jq -r '
    .items[]
    | {pod: .metadata.name,
    c: (.spec.containers + (.spec.initContainers // []))}
    | .pod as $pod
    | .c[]
    | select(.securityContext.allowPrivilegeEscalation == true)
    | "\($pod) \(.name) allowPrivilegeEscalation=true"
    ' || true
    echo
    done
    • Ensure remaining allowPrivilegeEscalation=true usages correspond only to explicitly documented exceptions or system/infra components you intentionally exempted.
Using kubectl
# 1) List all namespaces (for scoping your review)
# Run on: any machine with kubectl access
kubectl get namespaces -o name

Review which of these are user-workload namespaces (not kube-system, kube-public, etc.). For each user namespace, check for policies that restrict allowPrivilegeEscalation:

# 2) Check for validating admission policies related to allowPrivilegeEscalation
# Run on: any machine with kubectl access
kubectl get validatingadmissionpolicy,validatingadmissionpolicybinding -A

Problem indication:

  • No ValidatingAdmissionPolicy / ValidatingAdmissionPolicyBinding objects that reference allowPrivilegeEscalation or container security context fields.
  • Or they exist, but are not bound (Binding missing or paramRef misconfigured).

If you use Gatekeeper (OPA) for policy, inspect constraints:

# 3) List Gatekeeper constraints and templates (if used)
# Run on: any machine with kubectl access
kubectl get constrainttemplates -A
kubectl get constraints -A

Problem indication:

  • No constraint/template that enforces securityContext.allowPrivilegeEscalation=false on Pods/Workloads.
  • Constraints exist but are scoped only to a subset of namespaces that does not include your user-workload namespaces.

Now review actual workloads for allowPrivilegeEscalation usage. This is evidence, not the policy itself:

# 4) Inspect current pods in a namespace for allowPrivilegeEscalation
# Replace <NAMESPACE> with a user-workload namespace
# Run on: any machine with kubectl access
kubectl get pods -n <NAMESPACE> -o json \
| jq '.items[]
| { name: .metadata.name,
containers: [ .spec.containers[]
| { name: .name,
allowPrivilegeEscalation: ( .securityContext.allowPrivilegeEscalation // "unset" )
}
],
initContainers: ( .spec.initContainers // []
| [ .[]
| { name: .name,
allowPrivilegeEscalation: ( .securityContext.allowPrivilegeEscalation // "unset" )
}
]
)
}'

Problem indication:

  • Any container or initContainer shows "allowPrivilegeEscalation": true.
  • Many containers show "unset" and you have no admission policy forcing it to false (this typically means the setting is uncontrolled and could default to true depending on runtime/pod security configuration).

To focus only on containers where it is explicitly true:

# 5) Show only pods where any container/initContainer has allowPrivilegeEscalation=true
# Run on: any machine with kubectl access
kubectl get pods -n <NAMESPACE> -o json \
| jq '.items[]
| select(
([.spec.containers[]?.securityContext?.allowPrivilegeEscalation] // []) | any(. == true)
or
([.spec.initContainers[]?.securityContext?.allowPrivilegeEscalation] // []) | any(. == true)
)
| { name: .metadata.name }'

Problem indication:

  • Any pod names returned here represent workloads that currently run with allowPrivilegeEscalation=true.

Finally, inspect how pods are being created (Deployments, DaemonSets, etc.) to see if their templates set this flag:

# 6) Review workload specs for allowPrivilegeEscalation
# Run on: any machine with kubectl access

# Deployments
kubectl get deploy -n <NAMESPACE> -o yaml \
| grep -nA3 -B5 -E 'allowPrivilegeEscalation'

# DaemonSets
kubectl get ds -n <NAMESPACE> -o yaml \
| grep -nA3 -B5 -E 'allowPrivilegeEscalation'

# StatefulSets
kubectl get sts -n <NAMESPACE> -o yaml \
| grep -nA3 -B5 -E 'allowPrivilegeEscalation'

Problem indication:

  • Any workload templates explicitly set allowPrivilegeEscalation: true.
  • No compensating policy (from earlier steps) is in place for that namespace to block such specs from being admitted in the future.

These commands only surface the current state. Deciding which workloads (if any) may legitimately require allowPrivilegeEscalation=true, and designing namespace-scoped policies that enforce the desired standard while allowing justified exceptions, requires human review.

Automation
#!/usr/bin/env bash
# Report pods and (pod)security admission settings related to allowPrivilegeEscalation

set -euo pipefail

echo "=== 1) Pods with allowPrivilegeEscalation != false (or missing) ==="
echo "Namespace,Pod,Container,allowPrivilegeEscalation"
kubectl get pods --all-namespaces -o json \
| jq -r '
.items[]
| . as $pod
| (.metadata.namespace // "default") as $ns
| (.metadata.name // "") as $podname
| (
($pod.spec.initContainers // []) + ($pod.spec.containers // [])
)[]
| .name as $cname
| .securityContext.allowPrivilegeEscalation as $ape
| if $ape != false then
"\($ns),\($podname),\($cname),\($ape)"
else
empty
end
' | sort

cat <<'EOF'

[INTERPRETATION]
- Any CSV line printed above indicates a container that is *not* explicitly pinned to allowPrivilegeEscalation=false.
- allowPrivilegeEscalation values you may see:
- "false" (container is safe; if nothing prints, all are explicitly false)
- "true" (problem: container is allowed to escalate privileges)
- "null" (field not set; admission policy should normally prevent this or default it to false)
- Focus review on application namespaces (exclude kube-system / control-plane if required by your platform).

EOF

echo "=== 2) Namespace-level (Pod)Security admission labels (v1.25+) ==="
echo "Namespace,psa-profile,psa-enforce,psa-warn,psa-audit"
kubectl get ns --show-labels -o json \
| jq -r '
.items[]
| .metadata.name as $ns
| .metadata.labels as $l
| [
$ns,
($l["pod-security.kubernetes.io/profile"] // ""),
($l["pod-security.kubernetes.io/enforce"] // $l["pod-security.kubernetes.io/enforce-level"] // ""),
($l["pod-security.kubernetes.io/warn"] // ""),
($l["pod-security.kubernetes.io/audit"] // "")
]
| @csv
' | sort

cat <<'EOF'

[INTERPRETATION]
- For namespaces running user workloads, you generally want:
- enforce (or profile) level "restricted" (or stricter), which disallows allowPrivilegeEscalation=true.
- Potential problems:
- No PodSecurity labels at all on a user-workload namespace (empty columns).
- enforce/enforce-level set to "privileged" or "baseline" where you expect "restricted".
- warn/audit weaker than enforce can indicate drift or gaps to review.

EOF

echo "=== 3) PodSecurityPolicy objects (if still in use on older clusters) ==="
if kubectl api-resources | grep -q "^podsecuritypolicies"; then
kubectl get psp -o json \
| jq -r '
.items[]
| .metadata.name as $name
| .spec.allowPrivilegeEscalation as $ape
| .spec.defaultAllowPrivilegeEscalation as $dape
| "\($name),allowPrivilegeEscalation=\($ape),defaultAllowPrivilegeEscalation=\($dape)"
' | sort

cat <<'EOF'

[INTERPRETATION]
- PSPs that either:
- .spec.allowPrivilegeEscalation == true, or
- .spec.defaultAllowPrivilegeEscalation == true, or
- either field is null/omitted
may allow pods with allowPrivilegeEscalation=true to be admitted.
- Review which service accounts / namespaces are bound to such PSPs.

EOF
else
echo "PodSecurityPolicy API not found; skipping PSP review."
fi

Additional Reading: