Skip to main content

Minimize The Admission Of Containers With

More Info:

Containers with allowPrivilegeEscalation set to true can gain more privileges than their parent process. Restrict their admission via namespace policies.

Risk Level

High

Address

Security

Compliance Standards

  • CIS EKS

Triage and Remediation

Remediation

Manual Steps
  1. Identify namespaces with user workloads that allow privilege escalation
    Run on: any machine with kubectl access

    kubectl get pods --all-namespaces -o json | \
    jq -r '.items[]
    | select(any(.spec.containers[]?; .securityContext?.allowPrivilegeEscalation == true))
    | .metadata.namespace' | sort -u
  2. Create or update a Pod Security Admission configuration to forbid allowPrivilegeEscalation
    Run on: any machine with kubectl access
    Save this to a file, for example /tmp/psa-restrict-allow-priv-escalation.yaml:

    apiVersion: policy/v1
    kind: PodDisruptionBudget # placeholder kind to indicate MANUAL POLICY STEP
    metadata:
    name: MANUAL-REVIEW-POD-SECURITY-POLICY

    PodSecurityPolicy is deprecated/removed in most EKS clusters and there is no single standard policy object defined in the benchmark text. You must choose and configure a namespace-level admission control mechanism supported by your environment (for example: built-in Pod Security Admission labels pod-security.kubernetes.io/enforce=restricted, or a validating admission webhook such as Kyverno or OPA/Gatekeeper) to reject pods where any container has securityContext.allowPrivilegeEscalation: true. Follow your chosen tool’s documentation to create that policy and apply it to each user-workload namespace.

  3. Label user-workload namespaces to use the chosen restrictive policy mechanism
    Run on: any machine with kubectl access
    Example for built-in Pod Security Admission (if enabled in your cluster):

    # Replace <namespace> with each namespace from step 1 that holds user workloads
    kubectl label namespace <namespace> \
    pod-security.kubernetes.io/enforce=restricted \
    pod-security.kubernetes.io/audit=restricted \
    pod-security.kubernetes.io/warn=restricted --overwrite

    If using another mechanism (Kyverno, Gatekeeper, etc.), apply the equivalent namespace selectors/labels that make your “no allowPrivilegeEscalation=true” policy apply to those namespaces.

  4. Manually review and update existing workloads that currently set allowPrivilegeEscalation: true
    Run on: any machine with kubectl access
    List offending pods with owners to identify the controllers you must edit:

    kubectl get pods --all-namespaces -o json | \
    jq -r '.items[]
    | select(any(.spec.containers[]?; .securityContext?.allowPrivilegeEscalation == true))
    | .metadata.namespace + " " + .metadata.name + " " +
    ( .metadata.ownerReferences[0].kind // "Pod" ) + " " +
    ( .metadata.ownerReferences[0].name // .metadata.name )'

    For each controller (Deployment/DaemonSet/StatefulSet/Job/etc.), edit the manifest so that every container and initContainer either omits allowPrivilegeEscalation or explicitly sets it to false:

    # Example for a Deployment
    kubectl -n <namespace> edit deployment <name>

    In the editor, under each spec.template.spec.containers[].securityContext (and initContainers if present), ensure:

    securityContext:
    allowPrivilegeEscalation: false
  5. Recreate or restart workloads if needed to pick up policy-compliant settings
    Run on: any machine with kubectl access
    If you changed manifests in Git/IaC instead of with kubectl edit, apply them:

    kubectl apply -f <updated-manifest>.yaml

    For Helm-managed workloads, update the values and upgrade:

    helm upgrade <release-name> <chart> -n <namespace> -f <values>.yaml
  6. Verification
    Run on: any machine with kubectl access

    kubectl get pods --all-namespaces -o json | \
    jq -r 'if any(.items[]?.spec.containers[]?; .securityContext?.allowPrivilegeEscalation == true)
    then "ALLOWPRIVILEGEESCALTION_FOUND"
    else "NO_ALLOWPRIVILEGEESCALATION"
    end'

    Confirm the output is:

    NO_ALLOWPRIVILEGEESCALATION
Using kubectl
# 1) Create a baseline policy in each user workload namespace
# Replace <NAMESPACE> with your workload namespace name
# Run on: any machine with kubectl access

cat << 'EOF' | kubectl apply -f -
apiVersion: policy/v1
kind: PodSecurityPolicy
metadata:
name: disallow-allow-privilege-escalation
labels:
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/enforce: restricted
spec:
privileged: false
allowPrivilegeEscalation: false
defaultAllowPrivilegeEscalation: false
runAsUser:
rule: RunAsAny
seLinux:
rule: RunAsAny
fsGroup:
rule: RunAsAny
supplementalGroups:
rule: RunAsAny
volumes:
- '*'
EOF
# 2) Bind the policy in a specific namespace
# Replace <NAMESPACE> with your workload namespace name

cat << 'EOF' | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: use-psp-disallow-allow-privilege-escalation
namespace: <NAMESPACE>
rules:
- apiGroups: ['policy']
resources: ['podsecuritypolicies']
verbs: ['use']
resourceNames:
- disallow-allow-privilege-escalation
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: use-psp-disallow-allow-privilege-escalation
namespace: <NAMESPACE>
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: use-psp-disallow-allow-privilege-escalation
subjects:
# Adjust subjects to match who creates pods in this namespace
- kind: Group
name: system:serviceaccounts:<NAMESPACE>
apiGroup: rbac.authorization.k8s.io
EOF
# 3) (Optional) Repeat step 2 for each additional workload namespace
# Example for another namespace:
sed 's/namespace: <NAMESPACE>/namespace: my-workload-namespace-2/g' \
use-psp-disallow-allow-privilege-escalation.yaml | kubectl apply -f -

# 4) Verification: ensure no admitted pods have allowPrivilegeEscalation=true

kubectl get pods --all-namespaces -o json | \
jq -r 'if any(.items[]?.spec.containers[]?; .securityContext?.allowPrivilegeEscalation == true) then "ALLOWPRIVILEGEESCALTION_FOUND" else "NO_ALLOWPRIVILEGEESCALATION" end'
Automation
#!/usr/bin/env bash
set -euo pipefail

# This script:
# - Creates a Pod Security Admission restricted policy that disallows allowPrivilegeEscalation=true
# - Labels all non-system namespaces to use that policy
# - Verifies that no pods with allowPrivilegeEscalation=true exist
#
# Run on: any machine with kubectl access and context pointing to the target cluster.

# 1) Create/Update a restricted Pod Security Admission policy via a ValidatingAdmissionPolicy
# that forbids allowPrivilegeEscalation=true (in containers and initContainers).
# This is idempotent (kubectl apply).
cat <<'EOF' | kubectl apply -f -
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
name: disallow-allow-privilege-escalation
spec:
failurePolicy: Fail
matchConstraints:
resourceRules:
- apiGroups: [""]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["pods"]
validations:
- expression: "!(has(object.spec.containers) && object.spec.containers.exists(c, c.securityContext != null && c.securityContext.allowPrivilegeEscalation == true))"
message: "Containers must not set securityContext.allowPrivilegeEscalation=true"
- expression: "!(has(object.spec.initContainers) && object.spec.initContainers.exists(c, c.securityContext != null && c.securityContext.allowPrivilegeEscalation == true))"
message: "Init containers must not set securityContext.allowPrivilegeEscalation=true"
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicyBinding
metadata:
name: disallow-allow-privilege-escalation-binding
spec:
policyName: disallow-allow-privilege-escalation
validationActions:
- Deny
matchResources:
namespaceSelector:
matchExpressions:
- key: kubernetes.io/metadata.name
operator: NotIn
values:
- kube-system
- kube-public
- kube-node-lease
- default
EOF

# 2) Label all non-system namespaces that host user workloads, so they are clearly identified.
# Adjust the excluded list if needed. This is safe and idempotent.
for ns in $(kubectl get ns -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}'); do
case "$ns" in
kube-system|kube-public|kube-node-lease)
continue
;;
esac
# Label as a user-workload namespace (key is arbitrary but stable).
kubectl label ns "$ns" pod-security.kubernetes.io/user-workload=true --overwrite
done

# 3) Verification: ensure there are no pods with allowPrivilegeEscalation=true
# Matches the benchmark audit command.
echo "Running verification..."
kubectl get pods --all-namespaces -o json | \
jq -r 'if any(.items[]?.spec.containers[]?; .securityContext?.allowPrivilegeEscalation == true) then "ALLOWPRIVILEGEESCALTION_FOUND" else "NO_ALLOWPRIVILEGEESCALATION" end'