> ## 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.

# Containers Should Disallow Privilege Escalation

### More Info:

Verifies allowPrivilegeEscalation is false on every container. It defaults to true, letting a process gain more privileges than its parent.

### Risk Level

High

### Address

Security

### Compliance Standards

* Cloudanix Best Practice

### Triage and Remediation

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

    <AccordionGroup>
      <Accordion title="Manual Steps" defaultOpen="true">
        1. Identify all noncompliant Pods
           * On any machine with kubectl access:
             ```bash theme={null}
             kubectl get pods --all-namespaces -o json | jq -r '
               [ .items[]
               | select(.metadata.namespace as $n | ["kube-system","kube-public","kube-node-lease"] | index($n) | not)
               | .metadata as $m
               | (.spec.nodeName // "") as $node
               | (($m.labels // {}) | to_entries | map("\(.key):\(.value)") | join(",")) as $labels
               | ([ ($m.ownerReferences // [])[] | select(.controller) ] | first) as $own
               | ((.spec.containers // []) + (.spec.initContainers // []))[]
               | (.securityContext.allowPrivilegeEscalation == false) as $ok
               | select($ok | not)
               | "kind=Pod ns=\($m.namespace) name=\($m.name) uid=\($m.uid) apiVersion=v1"
                 + (if ($m.creationTimestamp // "") == "" then "" else " created=\($m.creationTimestamp)" end)
                 + (if $node   == ""   then "" else " node=\($node)" end)
                 + (if $labels == ""   then "" else " labels=\($labels)" end)
                 + (if $own    == null then "" else " owner=\($own.kind)/\($m.namespace)/\($own.name)/\($own.uid)" end)
                 + " container=\(.name) image=\(.image)"
                 + " allowPrivilegeEscalation=\(if .securityContext.allowPrivilegeEscalation == null then "unset" else .securityContext.allowPrivilegeEscalation end)"
               ][]'
             ```

        2. For Pods managed by higher-level controllers, patch the controller manifests
           * For each noncompliant Pod line with `owner=Deployment/…`, `ReplicaSet/…`, `StatefulSet/…`, or `DaemonSet/…`, note the `owner` kind, namespace, and name.
           * On any machine with kubectl access, edit the owning object (example for a Deployment; adapt `kind`, `namespace`, and `name` as needed):
             ```bash theme={null}
             kubectl -n <namespace> edit deployment <name>
             ```
           * In each `spec.template.spec.containers[]` and `spec.template.spec.initContainers[]` entry, ensure:
             ```yaml theme={null}
             securityContext:
               allowPrivilegeEscalation: false
             ```
             (add `securityContext` if missing; if present, add or set `allowPrivilegeEscalation: false`).

        3. For Pods created directly (no controller owner), edit and recreate them
           * For each noncompliant Pod line with no `owner=` field:
             ```bash theme={null}
             kubectl -n <namespace> get pod <pod-name> -o yaml > /tmp/pod-<namespace>-<pod-name>.yaml
             ```
           * Edit the file locally:
             ```bash theme={null}
             sed -i '/^\s*resourceVersion:/d;/^\s*uid:/d;/^\s*selfLink:/d;/^\s*managedFields:/d;/^\s*status:/d' /tmp/pod-<namespace>-<pod-name>.yaml
             ```
           * Open the file and, under `spec.containers[]` and `spec.initContainers[]` as needed, set:
             ```yaml theme={null}
             securityContext:
               allowPrivilegeEscalation: false
             ```
           * Delete and recreate the Pod:
             ```bash theme={null}
             kubectl -n <namespace> delete pod <pod-name>
             kubectl -n <namespace> apply -f /tmp/pod-<namespace>-<pod-name>.yaml
             ```

        4. If manifests are managed via Git/IaC, update source files
           * Locate the YAML/Helm/Kustomize definitions for the noncompliant workloads.
           * In each container and initContainer spec, set:
             ```yaml theme={null}
             securityContext:
               allowPrivilegeEscalation: false
             ```
           * Commit and apply/sync through your normal pipeline so the change persists.

        5. Consider namespace-wide policy to prevent regression (optional but recommended)
           * On any machine with kubectl access, create or update a `PodSecurity` admission label on namespaces where you want to enforce restricted settings, for example:
             ```bash theme={null}
             kubectl label namespace <namespace> pod-security.kubernetes.io/enforce=restricted --overwrite
             ```
           * Review workload compatibility before enforcing to avoid inadvertent disruptions.

        6. Verify remediation
           * After workloads are updated and reconciled, re-run the audit on any machine with kubectl access:
             ```bash theme={null}
             kubectl get pods --all-namespaces -o json | jq -r '
               [ .items[]
               | select(.metadata.namespace as $n | ["kube-system","kube-public","kube-node-lease"] | index($n) | not)
               | .metadata as $m
               | (.spec.nodeName // "") as $node
               | (($m.labels // {}) | to_entries | map("\(.key):\(.value)") | join(",")) as $labels
               | ([ ($m.ownerReferences // [])[] | select(.controller) ] | first) as $own
               | ((.spec.containers // []) + (.spec.initContainers // []))[]
               | (.securityContext.allowPrivilegeEscalation == false) as $ok
               | "kind=Pod ns=\($m.namespace) name=\($m.name) uid=\($m.uid) apiVersion=v1"
                 + (if ($m.creationTimestamp // "") == "" then "" else " created=\($m.creationTimestamp)" end)
                 + (if $node   == ""   then "" else " node=\($node)" end)
                 + (if $labels == ""   then "" else " labels=\($labels)" end)
                 + (if $own    == null then "" else " owner=\($own.kind)/\($m.namespace)/\($own.name)/\($own.uid)" end)
                 + " container=\(.name) image=\(.image)"
                 + " allowPrivilegeEscalation=\(if .securityContext.allowPrivilegeEscalation == null then "unset" else .securityContext.allowPrivilegeEscalation end)"
                 + " is_compliant=\(if $ok then "true" else "false" end)"
               ] as $rows
               | if ($rows | length) == 0 then "is_compliant=true" else $rows[] end'
             ```
           * Confirm the output is `is_compliant=true` or that all listed containers show `allowPrivilegeEscalation=false is_compliant=true`.
      </Accordion>

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

        1. Identify non‑compliant Pods and their owners (if any):

        ```bash theme={null}
        kubectl get pods --all-namespaces -o wide
        ```

        If the Pod is controlled by a higher‑level object (Deployment, DaemonSet, Job, etc.), edit that controller; otherwise edit the Pod directly.

        2. Patch a standalone Pod to disallow privilege escalation (all containers and initContainers):

        ```bash theme={null}
        kubectl patch pod POD_NAME \
          -n POD_NAMESPACE \
          --type='json' \
          -p='[
            {"op": "add", "path": "/spec/securityContext", "value": {}},
            {"op": "add", "path": "/spec/containers/0/securityContext", "value": {}}
          ]' 2>/dev/null || true

        kubectl get pod POD_NAME -n POD_NAMESPACE -o json \
          | jq '
            .spec.containers |= map(
              .securityContext.allowPrivilegeEscalation = false
            )
            | .spec.initContainers |= (// []) | . |= map(
              .securityContext.allowPrivilegeEscalation = false
            )' \
          | kubectl apply -f -
        ```

        3. Patch a Deployment so all its containers disallow privilege escalation:

        ```bash theme={null}
        kubectl get deployment DEPLOYMENT_NAME -n DEPLOYMENT_NAMESPACE -o json \
          | jq '
            .spec.template.spec.containers |= map(
              .securityContext.allowPrivilegeEscalation = false
            )
            | .spec.template.spec.initContainers |= (// []) | . |= map(
              .securityContext.allowPrivilegeEscalation = false
            )' \
          | kubectl apply -f -
        ```

        Repeat similarly for other controllers, replacing `deployment` with `daemonset`, `statefulset`, `job`, or `cronjob` as appropriate.

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

        ```bash theme={null}
        kubectl get pods --all-namespaces -o json | jq -r '
          [ .items[]
          | select(.metadata.namespace as $n | ["kube-system","kube-public","kube-node-lease"] | index($n) | not)
          | .metadata as $m
          | (.spec.nodeName // "") as $node
          | (($m.labels // {}) | to_entries | map("\(.key):\(.value)") | join(",")) as $labels
          | ([ ($m.ownerReferences // [])[] | select(.controller) ] | first) as $own
          | ((.spec.containers // []) + (.spec.initContainers // []))[]
          | (.securityContext.allowPrivilegeEscalation == false) as $ok
          | "kind=Pod ns=\($m.namespace) name=\($m.name) uid=\($m.uid) apiVersion=v1"
            + (if ($m.creationTimestamp // "") == "" then "" else " created=\($m.creationTimestamp)" end)
            + (if $node   == ""   then "" else " node=\($node)" end)
            + (if $labels == ""   then "" else " labels=\($labels)" end)
            + (if $own    == null then "" else " owner=\($own.kind)/\($m.namespace)/\($own.name)/\($own.uid)" end)
            + " container=\(.name) image=\(.image)"
            + " allowPrivilegeEscalation=\(if .securityContext.allowPrivilegeEscalation == null then "unset" else .securityContext.allowPrivilegeEscalation end)"
            + " is_compliant=\(if $ok then "true" else "false" end)"
          ] as $rows
          | if ($rows | length) == 0 then "is_compliant=true" else $rows[] end'
        ```
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        #
        # Remediation: Ensure all containers disallow privilege escalation
        # Benchmark: CBP C1.4
        #
        # Requirements:
        #   - kubectl configured with access to the cluster
        #   - jq installed
        #
        # Behavior:
        #   - Scans all non-system namespaces for Pods whose containers/initContainers
        #     do NOT have securityContext.allowPrivilegeEscalation=false
        #   - Patches their owning workload (Deployment/StatefulSet/DaemonSet/Job/CronJob/Pod)
        #     to set allowPrivilegeEscalation=false on every container and initContainer
        #   - Safe to re-run (idempotent)
        #   - Recreates Pods via normal controller behavior
        #
        # Run location:
        #   - Any machine with kubectl access to the cluster

        set -euo pipefail

        # -------- Config --------
        # Namespaces to ignore (system namespaces)
        IGNORE_NAMESPACES_REGEX='^(kube-system|kube-public|kube-node-lease)$'

        # -------- Helper functions --------
        log() { printf '[%s] %s\n' "$(date -u +'%Y-%m-%dT%H:%M:%SZ')" "$*"; }

        require_bin() {
          if ! command -v "$1" >/dev/null 2>&1; then
            echo "ERROR: '$1' not found in PATH" >&2
            exit 1
          fi
        }

        # jq filter used to set allowPrivilegeEscalation=false on all containers
        jq_patch_filter='
          .spec.template.spec as $spec
          | if $spec == null then . else
              .spec.template.spec =
              (
                $spec
                | if (.containers // null) != null then
                    .containers |= map(
                      .securityContext =
                        ((.securityContext // {}) + {allowPrivilegeEscalation:false})
                    )
                  else . end
                | if (.initContainers // null) != null then
                    .initContainers |= map(
                      .securityContext =
                        ((.securityContext // {}) + {allowPrivilegeEscalation:false})
                    )
                  else . end
              )
            end
        '

        jq_pod_patch_filter='
          .spec as $spec
          | if $spec == null then . else
              .spec =
              (
                $spec
                | if (.containers // null) != null then
                    .containers |= map(
                      .securityContext =
                        ((.securityContext // {}) + {allowPrivilegeEscalation:false})
                    )
                  else . end
                | if (.initContainers // null) != null then
                    .initContainers |= map(
                      .securityContext =
                        ((.securityContext // {}) + {allowPrivilegeEscalation:false})
                    )
                  else . end
              )
            end
        '

        # -------- Pre-flight checks --------
        require_bin kubectl
        require_bin jq

        # Verify cluster access
        kubectl version --short >/dev/null 2>&1 || {
          echo "ERROR: kubectl cannot reach the cluster" >&2
          exit 1
        }

        # -------- Discover non-compliant pods and their owners --------
        log "Discovering non-compliant Pods and their owners (excluding kube-system, kube-public, kube-node-lease)..."

        mapfile -t NONCOMPLIANT_LINES < <(
          kubectl get pods --all-namespaces -o json \
          | jq -r '
            .items[]
            | select(.metadata.namespace | test("'"$IGNORE_NAMESPACES_REGEX"'") | not)
            | . as $pod
            | (.spec.containers // [] + .spec.initContainers // []) as $cs
            | [ $cs[]
                | (.securityContext.allowPrivilegeEscalation == false) as $ok
                | select($ok | not)
              ] as $bad
            | select(($bad | length) > 0)
            | .metadata as $m
            | ([ ($m.ownerReferences // [])[] | select(.controller) ] | first) as $own
            | "ns=\($m.namespace) kind=\(if $own==null then "Pod" else $own.kind end) name=\(if $own==null then $m.name else $own.name end)"
          ' \
          | sort -u
        )

        if [ "${#NONCOMPLIANT_LINES[@]}" -eq 0 ]; then
          log "No non-compliant Pods found; cluster is already compliant."
        else
          log "Found ${#NONCOMPLIANT_LINES[@]} owning resources with non-compliant Pods."
        fi

        # -------- Patch owners --------
        for line in "${NONCOMPLIANT_LINES[@]}"; do
          ns=$(sed -E 's/^ns=([^ ]+).*/\1/' <<< "$line")
          kind=$(sed -E 's/.* kind=([^ ]+).*/\1/' <<< "$line")
          name=$(sed -E 's/.* name=([^ ]+).*/\1/' <<< "$line")

          # Normalize common controller kinds to kubectl resource types
          case "$kind" in
            Deployment)    res="deployment" ;;
            StatefulSet)   res="statefulset" ;;
            DaemonSet)     res="daemonset" ;;
            Job)           res="job" ;;
            CronJob)       res="cronjob" ;;
            Pod)           res="pod" ;;
            *)             res=$(tr '[:upper:]' '[:lower:]' <<< "$kind") ;;
          esac

          log "Processing $res/$ns/$name ..."

          # Fetch object
          if ! kubectl get "$res" "$name" -n "$ns" -o json >/tmp/aescalate-obj.json 2>/dev/null; then
            log "  WARN: Unable to fetch $res/$ns/$name; skipping."
            continue
          fi

          # Apply appropriate jq patch
          if [ "$res" = "pod" ]; then
            jq "$jq_pod_patch_filter" /tmp/aescalate-obj.json > /tmp/aescalate-obj-patched.json
          else
            jq "$jq_patch_filter" /tmp/aescalate-obj.json > /tmp/aescalate-obj-patched.json
          fi

          # If no change, skip
          if diff -q /tmp/aescalate-obj.json /tmp/aescalate-obj-patched.json >/dev/null 2>&1; then
            log "  No changes needed; already configured."
            continue
          fi

          # Apply patch with server-side apply to be idempotent and schema-safe
          if ! kubectl apply -f /tmp/aescalate-obj-patched.json >/dev/null 2>&1; then
            log "  ERROR: Failed to apply patch to $res/$ns/$name"
            continue
          fi

          log "  Patched $res/$ns/$name to set securityContext.allowPrivilegeEscalation=false on all containers."
        done

        rm -f /tmp/aescalate-obj.json /tmp/aescalate-obj-patched.json 2>/dev/null || true

        # -------- Verification --------
        log "Waiting briefly for controllers to reconcile pods..."
        sleep 10

        log "Verifying compliance with benchmark audit command..."

        audit_output=$(
        kubectl get pods --all-namespaces -o json | jq -r '
          [ .items[]
          | select(.metadata.namespace as $n | ["kube-system","kube-public","kube-node-lease"] | index($n) | not)
          | .metadata as $m
          | (.spec.nodeName // "") as $node
          | (($m.labels // {}) | to_entries | map("\(.key):\(.value)") | join(",")) as $labels
          | ([ ($m.ownerReferences // [])[] | select(.controller) ] | first) as $own
          | ((.spec.containers // []) + (.spec.initContainers // []))[]
          | (.securityContext.allowPrivilegeEscalation == false) as $ok
          | "kind=Pod ns=\($m.namespace) name=\($m.name) uid=\($m.uid) apiVersion=v1"
            + (if ($m.creationTimestamp // "") == "" then "" else " created=\($m.creationTimestamp)" end)
            + (if $node   == ""   then "" else " node=\($node)" end)
            + (if $labels == ""   then "" else " labels=\($labels)" end)
            + (if $own    == null then "" else " owner=\($own.kind)/\($m.namespace)/\($own.name)/\($own.uid)" end)
            + " container=\(.name) image=\(.image)"
            + " allowPrivilegeEscalation=\(if .securityContext.allowPrivilegeEscalation == null then "unset" else .securityContext.allowPrivilegeEscalation end)"
            + " is_compliant=\(if $ok then "true" else "false" end)"
          ] as $rows
          | if ($rows | length) == 0 then "is_compliant=true" else $rows[] end'
        )

        if grep -q '^is_compliant=true$' <<< "$audit_output"; then
          log "Verification succeeded: all checked Pods are compliant (allowPrivilegeEscalation=false)."
        else
          log "Verification found remaining non-compliant containers:"
          printf '%s\n' "$audit_output"
          exit 2
        fi

        exit 0
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
