> ## Documentation Index
> Fetch the complete documentation index at: https://cloudanix.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Minimize The Admission Of Containers With allowPrivilegeEscalation

### More Info:

allowPrivilegeEscalation lets a process gain more privileges than its parent. Blocking it limits in-container privilege escalation.

### Risk Level

High

### Address

Security

### Compliance Standards

* CIS Kubernetes

### Triage and Remediation

<Tabs>
  <Tab title="Remediation">
    ### Remediation

    <AccordionGroup>
      <Accordion title="Manual Steps" defaultOpen="true">
        1. **List pods with `allowPrivilegeEscalation: true` (any machine with kubectl access)**
           ```bash theme={null}
           kubectl get pods --all-namespaces -o json \
           | jq -r '.items[]
             | . as $pod
             | .spec.containers[]
             | select(.securityContext.allowPrivilegeEscalation == true)
             | "\($pod.metadata.namespace) \($pod.metadata.name) \(.name)"' \
           | sort -u
           ```
           Save this list; you will need it to update the workloads.

        2. **Review each affected workload and identify its owner (any machine with kubectl access)**\
           For each `<namespace> <pod> <container>` from step 1, get the owning controller (Deployment/DaemonSet/StatefulSet/Job/etc.):
           ```bash theme={null}
           NAMESPACE="<namespace>"
           POD="<pod_name>"

           kubectl get pod "$POD" -n "$NAMESPACE" -o jsonpath='{.metadata.ownerReferences}' | jq
           ```
           Use kind/name from `.kind` and `.name` to determine which resource/manifest you must change. If there is no ownerReference, the Pod is standalone and must be edited or recreated directly.

        3. **Decide policy: namespace-level restriction vs. per-workload hardening (any machine with kubectl access)**
           * If your cluster uses Pod Security Admission, consider labeling user namespaces with `pod-security.kubernetes.io/enforce=restricted` (or equivalent) only after confirming workloads can run without privilege escalation.
           * Otherwise, design or select an admission policy mechanism (e.g., Kyverno, OPA/Gatekeeper, custom admission webhook) that rejects Pods where any container has `securityContext.allowPrivilegeEscalation: true` or omits `securityContext` entirely.\
             This benchmark control is MANUAL: you must choose the appropriate tooling and exceptions model for your environment; there is no single mandatory configuration.

        4. **Harden workload manifests by setting `allowPrivilegeEscalation: false` (any machine with kubectl access)**\
           For each affected controller (Deployment, DaemonSet, etc.), edit its manifest (preferably in your Git/IaC repo) to set this on every container and initContainer:
           ```yaml theme={null}
           spec:
             template:
               spec:
                 containers:
                   - name: <container-name>
                     securityContext:
                       allowPrivilegeEscalation: false
                       # keep or add any other required securityContext fields
                 initContainers:
                   - name: <init-container-name>
                     securityContext:
                       allowPrivilegeEscalation: false
           ```
           Apply the updated manifest:
           ```bash theme={null}
           kubectl apply -f <path-to-updated-manifest>.yaml
           ```
           For standalone Pods generated without a controller, recreate them from an updated manifest containing the same change.

        5. **(Optional) Introduce a rejecting admission policy for future Pods (any machine with kubectl access)**\
           After confirming critical workloads function with `allowPrivilegeEscalation: false`, configure your chosen admission controller to:
           * Deny any Pod in user namespaces where any container or initContainer has `.securityContext.allowPrivilegeEscalation: true`.
           * Optionally also deny if the field is missing, to force explicit `false`.\
             Implement the policy using your platform’s recommended mechanism (e.g., Kyverno, Gatekeeper, PSA labels), then test in a non-production namespace before rolling out cluster-wide.

        6. **Verify remediation (any machine with kubectl access)**\
           Re-run the audit and confirm no containers report `is_compliant: false`:
           ```bash theme={null}
           kubectl get pods --all-namespaces -o custom-columns=POD_NAME:.metadata.name,POD_NAMESPACE:.metadata.namespace --no-headers | while read -r pod_name pod_namespace
           do
             kubectl get pod "${pod_name}" --namespace "${pod_namespace}" -o json | jq -c '.spec.containers[]' | while read -r container
             do
               container_name=$(echo ${container} | jq -r '.name')
               container_allowprivesc=$(echo ${container} | jq -r '.securityContext.allowPrivilegeEscalation' | sed -e 's/null/notset/g')
               if [ "${container_allowprivesc}" = "false" ] || [ "${container_allowprivesc}" = "notset" ]; then
                 echo "***pod_name: ${pod_name} container_name: ${container_name} pod_namespace: ${pod_namespace} is_container_allowprivesc: ${container_allowprivesc} is_compliant: true"
               else
                 echo "***pod_name: ${pod_name} container_name: ${container_name} pod_namespace: ${pod_namespace} is_container_allowprivesc: ${container_allowprivesc} is_compliant: false"
               fi
             done
           done
           ```
           Investigate and adjust any remaining `is_compliant: false` workloads or explicitly document them as approved exceptions.
      </Accordion>

      <Accordion title="Using kubectl">
        On any machine with kubectl access:

        1. Create a baseline restricted admission policy for each user-workload namespace\
           (example for namespace `prod-apps`; repeat per namespace with user workloads):

        ```bash theme={null}
        kubectl label namespace prod-apps pod-security.kubernetes.io/enforce=restricted --overwrite
        kubectl label namespace prod-apps pod-security.kubernetes.io/audit=restricted --overwrite
        kubectl label namespace prod-apps pod-security.kubernetes.io/warn=restricted --overwrite
        ```

        This uses the built-in “restricted” Pod Security Admission level, which disallows privilege escalation by default.

        2. For clusters/namespaces where you cannot (or do not want to) use PSA labels, create an explicit policy object.\
           a) If your cluster still supports PodSecurityPolicy (legacy), apply:

        ```yaml theme={null}
        # psp-deny-allowprivilegeescalation.yaml
        apiVersion: policy/v1beta1
        kind: PodSecurityPolicy
        metadata:
          name: deny-allow-priv-escalation
        spec:
          privileged: false
          allowPrivilegeEscalation: false
          requiredDropCapabilities:
            - ALL
          runAsUser:
            rule: MustRunAsNonRoot
          seLinux:
            rule: RunAsAny
          fsGroup:
            rule: RunAsAny
          supplementalGroups:
            rule: RunAsAny
          volumes:
            - 'configMap'
            - 'emptyDir'
            - 'projected'
            - 'secret'
            - 'downwardAPI'
            - 'persistentVolumeClaim'
        ```

        Apply it:

        ```bash theme={null}
        kubectl apply -f psp-deny-allowprivilegeescalation.yaml
        ```

        Then bind it to your workloads’ service accounts (example for namespace `prod-apps` using the default service account; adjust as needed):

        ```yaml theme={null}
        # rb-psp-deny-allowprivilegeescalation.yaml
        apiVersion: rbac.authorization.k8s.io/v1
        kind: Role
        metadata:
          name: use-deny-allow-priv-escalation-psp
          namespace: prod-apps
        rules:
          - apiGroups: ['policy']
            resources: ['podsecuritypolicies']
            verbs:     ['use']
            resourceNames: ['deny-allow-priv-escalation']
        ---
        apiVersion: rbac.authorization.k8s.io/v1
        kind: RoleBinding
        metadata:
          name: use-deny-allow-priv-escalation-psp
          namespace: prod-apps
        subjects:
          - kind: ServiceAccount
            name: default
            namespace: prod-apps
        roleRef:
          kind: Role
          name: use-deny-allow-priv-escalation-psp
          apiGroup: rbac.authorization.k8s.io
        ```

        Apply it:

        ```bash theme={null}
        kubectl apply -f rb-psp-deny-allowprivilegeescalation.yaml
        ```

        b) If your cluster uses another admission controller (e.g., Kyverno or OPA/Gatekeeper), define an equivalent rule that denies pods where `.spec.containers[*].securityContext.allowPrivilegeEscalation == true`. (This part is policy‑engine specific and must be created with its own CRDs; there is no generic kubectl-only object beyond what is shown above.)

        3. Update existing offending pods’ manifests so containers explicitly set `allowPrivilegeEscalation: false`.\
           Example pod spec snippet you should ensure for each container:

        ```yaml theme={null}
        spec:
          containers:
            - name: my-container
              image: my-image:tag
              securityContext:
                allowPrivilegeEscalation: false
        ```

        Apply updated workload manifests using your normal deployment process, or:

        ```bash theme={null}
        kubectl apply -f <your-updated-workload-manifest>.yaml
        ```

        4. Verification (run on any machine with kubectl):

        ```bash theme={null}
        kubectl get pods --all-namespaces -o custom-columns=POD_NAME:.metadata.name,POD_NAMESPACE:.metadata.namespace --no-headers | while read -r pod_name pod_namespace
        do
          kubectl get pod "${pod_name}" --namespace "${pod_namespace}" -o json | jq -c '.spec.containers[]' | while read -r container
          do
            container_name=$(echo ${container} | jq -r '.name')
            container_allowprivesc=$(echo ${container} | jq -r '.securityContext.allowPrivilegeEscalation' | sed -e 's/null/notset/g')
            if [ "${container_allowprivesc}" = "false" ] || [ "${container_allowprivesc}" = "notset" ]; then
              echo "***pod_name: ${pod_name} container_name: ${container_name} pod_namespace: ${pod_namespace} is_container_allowprivesc: ${container_allowprivesc} is_compliant: true"
            else
              echo "***pod_name: ${pod_name} container_name: ${container_name} pod_namespace: ${pod_namespace} is_container_allowprivesc: ${container_allowprivesc} is_compliant: false"
            fi
          done
        done
        ```
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        #
        # Enforce: Minimize the admission of containers with allowPrivilegeEscalation=true
        # Scope: Any machine with kubectl access to the cluster
        #
        # Strategy:
        # - For every namespace that is intended for user workloads, create/update a
        #   Pod Security admission label to enforce the "restricted" policy at
        #   enforce level. The restricted profile blocks allowPrivilegeEscalation by default.
        # - This script is idempotent and safe to re-run.
        #
        # IMPORTANT:
        # - You must adjust the NAMESPACE_FILTER below to match your environment.
        #   By default, this script targets all namespaces EXCEPT a small set of
        #   common system namespaces, which is often what "user workloads" means.
        # - The benchmark is MANUAL: you must review which namespaces should be
        #   protected before running this.

        set -euo pipefail

        # ------------- CONFIGURATION (EDIT TO SUIT YOUR CLUSTER) --------------------

        # Regex pattern of namespaces to EXCLUDE from restricted policy enforcement.
        # These are assumed to be system/control-plane namespaces.
        EXCLUDE_NS_REGEX='^(kube-system|kube-public|kube-node-lease|kube-*|default|istio-system|linkerd|cilium-system|tigera-operator|calico-system|monitoring|logging)$'

        # Pod Security Admission label key/value for restricted policy at enforce level.
        PSA_ENFORCE_KEY="pod-security.kubernetes.io/enforce"
        PSA_ENFORCE_VALUE="restricted"

        # ---------------------------------------------------------------------------

        # Ensure kubectl is available and we can reach the cluster.
        if ! command -v kubectl >/dev/null 2>&1; then
          echo "ERROR: kubectl not found in PATH. Install kubectl and ensure it can reach the cluster." >&2
          exit 1
        fi

        if ! kubectl version --request-timeout=5s >/dev/null 2>&1; then
          echo "ERROR: Unable to talk to the Kubernetes API with kubectl." >&2
          exit 1
        fi

        echo "Discovering namespaces intended for user workloads..."
        # List all namespaces, then filter out excluded/system namespaces.
        USER_NS_LIST=$(
          kubectl get ns -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' \
          | grep -Ev "${EXCLUDE_NS_REGEX}" || true
        )

        if [ -z "${USER_NS_LIST}" ]; then
          echo "No user-workload namespaces matched. Nothing to do."
          exit 0
        fi

        echo "Namespaces selected for restricted Pod Security enforcement:"
        echo "${USER_NS_LIST}" | sed 's/^/  - /'

        # Apply/Update Pod Security Admission labels on each user namespace
        for ns in ${USER_NS_LIST}; do
          echo "Applying PSA 'restricted' policy to namespace: ${ns}"

          # Check existing label value (if any)
          current_value=$(kubectl get ns "${ns}" -o jsonpath="{.metadata.labels.${PSA_ENFORCE_KEY}}" 2>/dev/null || true)

          if [ "${current_value}" = "${PSA_ENFORCE_VALUE}" ]; then
            echo "  Namespace ${ns} already has ${PSA_ENFORCE_KEY}=${PSA_ENFORCE_VALUE} (no change)."
            continue
          fi

          if [ -n "${current_value}" ]; then
            echo "  Updating ${PSA_ENFORCE_KEY} from '${current_value}' to '${PSA_ENFORCE_VALUE}' on namespace ${ns}."
          else
            echo "  Setting ${PSA_ENFORCE_KEY}=${PSA_ENFORCE_VALUE} on namespace ${ns}."
          fi

          kubectl label ns "${ns}" "${PSA_ENFORCE_KEY}=${PSA_ENFORCE_VALUE}" --overwrite
        done

        echo
        echo "Verification: Pod Security Admission labels in user-workload namespaces"
        kubectl get ns ${USER_NS_LIST} -o custom-columns=NAME:.metadata.name,ENFORCE:.metadata.labels.pod-security\\.kubernetes\\.io/enforce

        echo
        echo "Additional verification of running Pods' allowPrivilegeEscalation values:"
        kubectl get pods --all-namespaces -o custom-columns=POD_NAME:.metadata.name,POD_NAMESPACE:.metadata.namespace --no-headers | while read -r pod_name pod_namespace
        do
          kubectl get pod "${pod_name}" --namespace "${pod_namespace}" -o json | jq -c '.spec.containers[]' | while read -r container
          do
            container_name=$(echo "${container}" | jq -r '.name')
            container_allowprivesc=$(echo "${container}" | jq -r '.securityContext.allowPrivilegeEscalation' | sed -e 's/null/notset/g')
            if [ "${container_allowprivesc}" = "false" ] || [ "${container_allowprivesc}" = "notset" ]; then
              echo "***pod_name: ${pod_name} container_name: ${container_name} pod_namespace: ${pod_namespace} is_container_allowprivesc: ${container_allowprivesc} is_compliant: true"
            else
              echo "***pod_name: ${pod_name} container_name: ${container_name} pod_namespace: ${pod_namespace} is_container_allowprivesc: ${container_allowprivesc} is_compliant: false"
            fi
          done
        done

        echo
        echo "NOTE:"
        echo "- New Pods in the labeled namespaces must comply with the 'restricted' profile,"
        echo "  which disallows privilege escalation unless explicitly configured otherwise."
        echo "- Existing non-compliant Pods may continue running until they are recreated."
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
