> ## 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 Containers With Added Capabilities

### More Info:

Do not generally permit containers with capabilities assigned beyond the default set.

### Risk Level

Medium

### Address

Security

### Compliance Standards

* APRA CPS 234 (Australia)
* BSI C5 (Germany)
* Brazil LGPD
* CCPA / CPRA (California)
* CIS Critical Security Controls v8
* CIS EKS
* 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)
* NIS2 Directive
* 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

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

    <AccordionGroup>
      <Accordion title="Manual Steps" defaultOpen="true">
        1. **Inventory pods and their capabilities**
           * Run on: any machine with kubectl access
           ```bash theme={null}
           kubectl get pods --all-namespaces -o json \
           | jq -r '.items[]
             | .metadata.namespace as $ns
             | .metadata.name as $pod
             | (.spec.initContainers // [] + .spec.containers // [])
             | .[]
             | {
                 ns: $ns,
                 pod: $pod,
                 container: .name,
                 seccomp: (.securityContext.seccompProfile.type // "unset"),
                 cap_add: (.securityContext.capabilities.add // []),
                 cap_drop: (.securityContext.capabilities.drop // [])
               }
             | select((.cap_add | length) > 0)
             | "\(.ns) \(.pod) \(.container) add=\(.cap_add) drop=\(.cap_drop) seccomp=\(.seccomp)"
           '
           ```
           This lists all containers that explicitly add Linux capabilities.

        2. **Classify namespaces and workloads by business/operational need**
           * Identify security-sensitive or “least privilege” namespaces (e.g., `prod`, `payments`, `default` for shared apps).
           * For each namespace found in step 1, list workloads and owners:
           ```bash theme={null}
           kubectl get deploy,sts,ds,job,cronjob -A -o wide
           ```
           * Map each workload to an application/team and document whether it truly requires added capabilities (e.g., `NET_ADMIN`, `SYS_ADMIN`, `DAC_OVERRIDE`).

        3. **Validate necessity of each added capability with workload owners**
           * For each `(namespace, pod, container)` with `capabilities.add` from step 1:
             * Retrieve the full pod spec and security context:
             ```bash theme={null}
             kubectl get pod -n <NAMESPACE> <POD_NAME> -o yaml
             ```
             * Review with the application owner:
               * What specific feature requires each capability?
               * Can the feature be implemented using standard permissions (RBAC, read-only FS, non-root UID) instead of Linux capabilities?
               * Can the capability be replaced with a smaller set or removed entirely?

        4. **Harden pod specs by dropping unnecessary capabilities**
           * For workloads where capabilities are not strictly needed, update their manifests (Deployments/StatefulSets/DaemonSets/Jobs/CronJobs) to remove `.securityContext.capabilities.add` and, where possible, drop all capabilities:
           ```yaml theme={null}
           securityContext:
             runAsNonRoot: true
             allowPrivilegeEscalation: false
             capabilities:
               drop:
                 - ALL
           ```
           * Apply the updated manifests:
           ```bash theme={null}
           kubectl apply -f <UPDATED-MANIFEST>.yaml
           ```
           * Confirm the running pods no longer have added capabilities:
           ```bash theme={null}
           kubectl get pod -n <NAMESPACE> <POD_NAME> -o json \
           | jq '.spec.containers[].securityContext.capabilities'
           ```

        5. **Enforce “no extra capabilities” at the namespace level where appropriate**
           * For namespaces whose workloads do not need any Linux capabilities, implement a guarding admission policy (e.g., Pod Security Standards `restricted` or an admission controller / policy engine that forbids `capabilities.add` and/or enforces `drop: ["ALL"]`).
           * Example (if using Pod Security Admission labels):
           ```bash theme={null}
           kubectl label namespace <NAMESPACE> \
             pod-security.kubernetes.io/enforce=restricted \
             --overwrite
           ```
           * Then verify new pods in that namespace cannot be created with added capabilities (attempt a test pod with `capabilities.add` and ensure it is rejected).

        6. **Re-audit and document residual exceptions**
           * Re-run the capability inventory to confirm reduction:
           ```bash theme={null}
           kubectl get pods --all-namespaces -o json | jq '…'   # reuse command from step 1
           ```
           * For any remaining containers with added capabilities:
             * Ensure there is documented justification, approval, and a review date.
             * Consider adding dedicated “high-privilege” namespaces for them and applying stricter monitoring/alerting on those workloads.
      </Accordion>

      <Accordion title="Using kubectl">
        ```bash theme={null}
        # 1) List all pods and their containers’ security contexts (cluster-wide)
        # Run on: any machine with kubectl access
        kubectl get pods --all-namespaces -o jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.metadata.name}{"\n"}{range .spec.initContainers[*]}{"  initContainer: "}{.name}{"\n"}{"    securityContext: "}{@.securityContext}{"\n"}{end}{range .spec.containers[*]}{"  container: "}{.name}{"\n"}{"    securityContext: "}{@.securityContext}{"\n"}{end}{"\n"}{end}' \
          | sed 's/ map\[/ {/g' | sed 's/\]}/}/g'
        ```

        Problem indication: Containers or initContainers showing `capabilities.add` or missing `capabilities.drop` where your policy expects `drop: ["ALL"]`.

        ***

        ```bash theme={null}
        # 2) Directly list containers that add capabilities (cluster-wide)
        # Run on: any machine with kubectl access
        kubectl get pods --all-namespaces -o json \
          | jq -r '
            .items[]
            | .metadata as $m
            | (.spec.initContainers // [])[]? as $c
              | select($c.securityContext.capabilities.add != null)
              | "NAMESPACE=\($m.namespace)\tPOD=\($m.name)\tTYPE=initContainer\tCONTAINER=\($c.name)\tADDED_CAPS=\($c.securityContext.capabilities.add)"
            ,
            (.spec.containers // [])[]? as $c
              | select($c.securityContext.capabilities.add != null)
              | "NAMESPACE=\($m.namespace)\tPOD=\($m.name)\tTYPE=container\tCONTAINER=\($c.name)\tADDED_CAPS=\($c.securityContext.capabilities.add)"
          '
        ```

        Problem indication: Any line returned here is a workload explicitly adding Linux capabilities and must be reviewed for necessity.

        ***

        ```bash theme={null}
        # 3) List containers that do NOT drop all capabilities (where securityContext is set)
        # Run on: any machine with kubectl access
        kubectl get pods --all-namespaces -o json \
          | jq -r '
            .items[]
            | .metadata as $m
            | (.spec.initContainers // [])[]? as $c
              | select($c.securityContext != null)
              | select( (.securityContext.capabilities.drop // []) | index("ALL") | not )
              | "NAMESPACE=\($m.namespace)\tPOD=\($m.name)\tTYPE=initContainer\tCONTAINER=\($c.name)\tDROP=\($c.securityContext.capabilities.drop // [])"
            ,
            (.spec.containers // [])[]? as $c
              | select($c.securityContext != null)
              | select( (.securityContext.capabilities.drop // []) | index("ALL") | not )
              | "NAMESPACE=\($m.namespace)\tPOD=\($m.name)\tTYPE=container\tCONTAINER=\($c.name)\tDROP=\($c.securityContext.capabilities.drop // [])"
          '
        ```

        Problem indication: In namespaces where you intend workloads to run without capabilities, any container listed here is not configured to `drop: ["ALL"]` and should be examined.

        ***

        ```bash theme={null}
        # 4) Inspect security policies that control capabilities (PSP, PodSecurityPolicy) – if present
        # Run on: any machine with kubectl access
        kubectl get psp -o yaml
        ```

        Problem indication: For namespaces where no capabilities should be allowed, corresponding PodSecurityPolicies should:

        * either require `drop: ["ALL"]` for container capabilities, or
        * otherwise ensure no additional capabilities can be added.

        If no such PSP (or equivalent admission policy) exists for those namespaces, admission is not minimized as recommended.

        ***

        ```bash theme={null}
        # 5) For a specific namespace you believe should NOT use capabilities, review all pods
        # Replace NAMESPACE with the actual namespace name
        # Run on: any machine with kubectl access
        NAMESPACE=kube-system  # example; change as needed
        kubectl get pods -n "$NAMESPACE" -o json \
          | jq -r '
            .items[]
            | .metadata.name as $pod
            | (.spec.initContainers // [])[]? as $c
              | "POD=\($pod)\tTYPE=initContainer\tCONTAINER=\($c.name)\tCAPS=\($c.securityContext.capabilities // {})"
            ,
            (.spec.containers // [])[]? as $c
              | "POD=\($pod)\tTYPE=container\tCONTAINER=\($c.name)\tCAPS=\($c.securityContext.capabilities // {})"
          '
        ```

        Problem indication: In that namespace, containers showing `capabilities.add` or not dropping all capabilities where your policy expects no capabilities are candidates for redesign or exemption.
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        # Report pods and controllers that add Linux capabilities beyond the default/drop-all
        # Run on: any machine with kubectl access
        # Requirements: kubectl, jq

        set -euo pipefail

        echo "=== POD-LEVEL CAPABILITIES (all namespaces) ==="
        kubectl get pods --all-namespaces -o json \
          | jq -r '
            .items[]
            | . as $pod
            | ($pod.spec.initContainers[]?, $pod.spec.containers[]?) as $c
            | {
                ns: $pod.metadata.namespace,
                pod: $pod.metadata.name,
                container: $c.name,
                add: $c.securityContext.capabilities.add // [],
                drop: $c.securityContext.capabilities.drop // [],
                privileged: $c.securityContext.privileged // false,
                allowPrivEsc: $c.securityContext.allowPrivilegeEscalation // "unset",
                runAsUser: $c.securityContext.runAsUser // "unset",
                runAsNonRoot: $c.securityContext.runAsNonRoot // "unset"
              }
            | select(
                (.add | length > 0)
                or
                ((.drop | length == 0) and (.add | length > 0))
                or
                (.privileged == true)
              )
            | "NAMESPACE=\(.ns) POD=\(.pod) CONTAINER=\(.container)\n  add_caps=\(.add)\n  drop_caps=\(.drop)\n  privileged=\(.privileged)\n  allowPrivilegeEscalation=\(.allowPrivEsc)\n  runAsUser=\(.runAsUser) runAsNonRoot=\(.runAsNonRoot)\n"
          '

        echo
        echo "=== CONTROLLER TEMPLATES (Deployments, DaemonSets, StatefulSets, Jobs, CronJobs) ==="
        for kind in deployment daemonset statefulset job cronjob; do
          echo "--- $kind(s) ---"
          kubectl get "$kind" --all-namespaces -o json 2>/dev/null \
            | jq -r '
              .items[]
              | . as $obj
              | ( .spec.template.spec.initContainers[]?, .spec.template.spec.containers[]? ) as $c
              | {
                  apiVersion: $obj.apiVersion,
                  kind: $obj.kind,
                  ns: $obj.metadata.namespace,
                  name: $obj.metadata.name,
                  container: $c.name,
                  add: $c.securityContext.capabilities.add // [],
                  drop: $c.securityContext.capabilities.drop // [],
                  privileged: $c.securityContext.privileged // false,
                  allowPrivEsc: $c.securityContext.allowPrivilegeEscalation // "unset",
                  runAsUser: $c.securityContext.runAsUser // "unset",
                  runAsNonRoot: $c.securityContext.runAsNonRoot // "unset"
                }
              | select(
                  (.add | length > 0)
                  or
                  ((.drop | length == 0) and (.add | length > 0))
                  or
                  (.privileged == true)
                )
              | "NS=\(.ns) KIND=\(.kind) NAME=\(.name) CONTAINER=\(.container)\n  add_caps=\(.add)\n  drop_caps=\(.drop)\n  privileged=\(.privileged)\n  allowPrivilegeEscalation=\(.allowPrivEsc)\n  runAsUser=\(.runAsUser) runAsNonRoot=\(.runAsNonRoot)\n"
            ' || true
        done

        echo
        echo "=== NAMESPACE-LEVEL POD SECURITY (PodSecurity or PodSecurityPolicies, if present) ==="
        echo "-- Namespaces with Pod Security Admission labels (v1.25+ recommended) --"
        kubectl get ns --show-labels | grep -E 'pod-security.kubernetes.io/(enforce|audit|warn)=' || echo "No Pod Security labels found."

        echo
        echo "-- PodSecurityPolicies (if any; deprecated but still relevant where enabled) --"
        kubectl get podsecuritypolicies.policy 2>/dev/null -o json \
          | jq -r '
            .items[]
            | {
                name: .metadata.name,
                allowedCaps: .spec.allowedCapabilities // [],
                requiredDropCaps: .spec.requiredDropCapabilities // [],
                defaultAddCaps: .spec.defaultAddCapabilities // []
              }
            | "PSP=\(.name)\n  allowedCapabilities=\(.allowedCaps)\n  requiredDropCapabilities=\(.requiredDropCaps)\n  defaultAddCapabilities=\(.defaultAddCaps)\n"
          ' || echo "No PodSecurityPolicies found."

        cat <<'EOF'

        INTERPRETING OUTPUT (what indicates a potential problem):

        1) POD-LEVEL / CONTROLLER OUTPUT:
           - Any line with non-empty "add_caps" is a candidate for review:
               add_caps=["NET_ADMIN","SYS_ADMIN"]
             Check if each listed capability is strictly required.
           - If "drop_caps" is empty or does not include "ALL", and add_caps is non-empty,
             the container is not dropping all capabilities before adding back a minimal set.
           - Any "privileged=true" container is very high risk and should be scrutinized.

        2) NAMESPACE / POLICY OUTPUT:
           - Namespaces lacking Pod Security Admission labels likely have weaker default
             restrictions; consider adding labels to enforce restricted or baseline policies.
           - PodSecurityPolicies (if present) that:
               * have broad "allowedCapabilities" (e.g., ["*"] or many powerful caps), or
               * do NOT include "ALL" in "requiredDropCapabilities"
             may allow admission of overly-privileged pods in those namespaces.

        Use this report to:
           - Identify workloads that add Linux capabilities or run privileged.
           - Confirm whether your pod-security mechanisms actually prevent such pods in
             namespaces where they are not required.
           - Decide, per application/namespace, whether to tighten manifests or policies.
        EOF
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>

### Additional Reading:

* [https://kubernetes.io/docs/concepts/security/pod-security-standards/](https://kubernetes.io/docs/concepts/security/pod-security-standards/)
