> ## 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 Capabilities Assigned

### More Info:

Do not generally permit containers with capabilities

### Risk Level

Low

### 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. On any machine with kubectl access, list all namespaces and identify those that should be “locked down” (no workloads needing Linux capabilities), for example dev/test or simple stateless apps:
           ```bash theme={null}
           kubectl get ns --show-labels
           ```
           Optionally label target namespaces for easier selection:
           ```bash theme={null}
           kubectl label ns <namespace> security.capabilities=restricted
           ```

        2. For each candidate namespace, inspect all running workloads for explicit capability use in `securityContext`:
           ```bash theme={null}
           # Pods
           kubectl get pods -n <namespace> -o yaml | grep -nE 'capabilities|allowPrivilegeEscalation|privileged'

           # Workloads (Deployments, DaemonSets, StatefulSets, Jobs, CronJobs)
           kubectl get deploy,ds,sts,job,cronjob -n <namespace> -o yaml | grep -nE 'capabilities|allowPrivilegeEscalation|privileged'
           ```
           If any container uses `securityContext.capabilities.add` or runs privileged / with `allowPrivilegeEscalation: true`, confirm with the app owner whether this is truly required.

        3. For containers that do not require capabilities, plan to standardize on dropping all capabilities, either at the pod spec or via a restrictive Pod Security configuration. Example pod-level setting to recommend to app owners:
           ```yaml theme={null}
           securityContext:
             runAsNonRoot: true
             allowPrivilegeEscalation: false
             capabilities:
               drop:
                 - ALL
           ```

        4. If your cluster still uses PodSecurityPolicy and it is enabled, create or select a PSP that requires dropping all capabilities and denies additional ones, and bind it only to namespaces whose workloads do not need capabilities. Example PSP manifest to adapt and apply:
           ```yaml theme={null}
           apiVersion: policy/v1beta1
           kind: PodSecurityPolicy
           metadata:
             name: drop-all-caps
           spec:
             privileged: false
             allowPrivilegeEscalation: false
             requiredDropCapabilities:
               - ALL
             allowedCapabilities: []
             volumes:
               - 'configMap'
               - 'emptyDir'
               - 'projected'
               - 'secret'
               - 'downwardAPI'
               - 'persistentVolumeClaim'
             runAsUser:
               rule: 'MustRunAsNonRoot'
             seLinux:
               rule: 'RunAsAny'
             fsGroup:
               rule: 'MustRunAs'
               ranges:
                 - min: 1
                   max: 65535
             supplementalGroups:
               rule: 'MustRunAs'
               ranges:
                 - min: 1
                   max: 65535
           ```
           Then bind it to service accounts in the target namespace:
           ```bash theme={null}
           kubectl create role psp:drop-all-caps --verb=use --resource=podsecuritypolicies.policy --resource-name=drop-all-caps -n <namespace>
           kubectl create rolebinding psp:drop-all-caps \
             --role=psp:drop-all-caps \
             --serviceaccount=<namespace>:default \
             -n <namespace>
           ```

        5. If PSP is not available (or you are on newer Kubernetes), use Pod Security Admission / Pod Security Standards or an equivalent policy engine (e.g., OPA Gatekeeper, Kyverno) to enforce “drop all capabilities” on selected namespaces. For Pod Security Admission, set namespaces to a strict level and then verify the effect:
           ```bash theme={null}
           kubectl label ns <namespace> pod-security.kubernetes.io/enforce=restricted \
             pod-security.kubernetes.io/enforce-version=latest --overwrite

           # Attempt to admit a pod that adds capabilities; it should be rejected
           kubectl apply -n <namespace> -f - <<'EOF'
           apiVersion: v1
           kind: Pod
           metadata:
             name: test-add-cap
           spec:
             containers:
               - name: c
                 image: alpine
                 command: ["sleep","3600"]
                 securityContext:
                   capabilities:
                     add: ["NET_ADMIN"]
           EOF
           ```

        6. Re‑audit periodically to ensure no capability use has crept back into “locked down” namespaces, and that your policy is correctly preventing admission:
           ```bash theme={null}
           # Check for capabilities in all pods in locked-down namespaces
           kubectl get ns -l security.capabilities=restricted -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' \
           | xargs -I{} sh -c 'echo "Namespace: {}"; kubectl get pods -n {} -o yaml | grep -nE "capabilities|privileged|allowPrivilegeEscalation" || echo "  No explicit capabilities found"'
           ```
      </Accordion>

      <Accordion title="Using kubectl">
        ### Using kubectl

        Run these from any machine with `kubectl` access.

        #### 1. List all pods and surface explicit capabilities

        ```sh theme={null}
        kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}{";"}{.metadata.name}{";"}{range .spec.containers[*]}{.name}{";"}{.securityContext.capabilities}{"|"}{end}{"\n"}{end}' \
        | column -s';' -t
        ```

        What indicates a problem:

        * Any container showing `add: [...]` with capabilities (for example `CAP_SYS_ADMIN`, `CAP_NET_ADMIN`, `CAP_SYS_PTRACE`) in namespaces that are not known to need them.
        * Containers with no `drop` list, or that don’t include `ALL` in `drop`, especially when `add` is present.

        #### 2. Inspect full securityContext for specific namespaces

        Review “application” namespaces (replace with your namespaces):

        ```sh theme={null}
        kubectl get pods -n default -o yaml | less
        kubectl get pods -n production -o yaml | less
        ```

        In each pod, look under `.spec.containers[].securityContext.capabilities` and note:

        * `add:` entries: which capabilities are being granted.
        * `drop:` entries: whether `ALL` is dropped or only some caps.

        Problem indicators:

        * Capabilities added without a clear, documented need.
        * Security context missing entirely for workloads that may rely on defaults you do not control.

        #### 3. Check for PodSecurityPolicy (or replacement) enforcing dropped capabilities

        If PSP is still in use:

        ```sh theme={null}
        kubectl get psp -o yaml | less
        ```

        Look for:

        * `spec.requiredDropCapabilities` including `ALL`, or a broad set of drops.
        * `spec.allowedCapabilities` being empty or very restricted.

        Problem indicators:

        * No PSPs present.
        * PSPs that allow broad capabilities (`allowedCapabilities: ["*"]` or many capabilities) and are bound to general-purpose namespaces.

        If using Pod Security Admission (PSA) labels instead of PSP:

        ```sh theme={null}
        kubectl get ns --show-labels
        ```

        Problem indicators:

        * Application namespaces without restrictive pod security labels (for example, not set to `restricted`) while workloads in them are using elevated capabilities.

        #### 4. Map which PSPs (if any) apply to a namespace

        If RBAC + PSP are used, list role bindings in a namespace:

        ```sh theme={null}
        kubectl get rolebindings,clusterrolebindings -n default -o yaml | less
        ```

        Look for:

        * `ClusterRole` or `Role` that references a PSP.
        * Which service accounts in the namespace are bound to permissive PSPs.

        Problem indicators:

        * Service accounts in a namespace bound (directly or indirectly) to highly permissive PSPs while workloads do not need extra capabilities.

        #### 5. Spot risky capabilities via label/annotation search

        Search for pods likely using custom security settings:

        ```sh theme={null}
        kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}{" "}{.metadata.name}{" "}{.metadata.annotations}{"\n"}{end}' | grep -i security
        ```

        Then examine interesting pods in detail:

        ```sh theme={null}
        kubectl get pod <pod-name> -n <namespace> -o yaml | less
        ```

        Problem indicators:

        * Annotations or settings that explicitly relax security controls while the application does not clearly require them.

        #### 6. Human review guidance

        Use the above data to decide, per namespace:

        * Does any workload in this namespace truly require Linux capabilities (for example, low-level networking, mounting filesystems, time sync, etc.)?
        * If **no**, this namespace is a good candidate to:
          * Ensure workloads drop all capabilities, and
          * Attach policies (PSP or its replacement) that forbid adding capabilities / require dropping all.

        There is no single kubectl command to decide this automatically; it requires understanding what each application does and whether the capabilities are strictly necessary.
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        # Report pods and workloads that use Linux capabilities, per namespace.
        # Run on: any machine with kubectl access and a current context.

        set -euo pipefail

        echo "=== 1) Namespaces and whether they enforce dropping all capabilities (PodSecurityPolicy) ==="
        echo "NOTE: PSP is deprecated/removed in recent Kubernetes; skip this section if not in use."
        echo

        # List PSPs that require all capabilities to be dropped
        echo "# PodSecurityPolicies that enforce 'drop: [ALL]' (good controls to bind to non-privileged namespaces):"
        kubectl get psp -o json 2>/dev/null | jq -r '
          .items[]
          | select(
              (.spec.requiredDropCapabilities // []) as $req
              | ($req | index("ALL")) != null
            )
          | "- " + .metadata.name
        ' || echo "PSP API not available or jq not installed; skip PSP analysis."

        echo
        echo "=== 2) Pods with capabilities in their securityContext (per namespace) ==="
        echo

        # Show per-pod container capabilities
        kubectl get pods -A -o json | jq -r '
          .items[]
          | {
              ns: .metadata.namespace,
              pod: .metadata.name,
              containers: (
                [.spec.containers[]? | {
                  name,
                  cap_add:   (.securityContext.capabilities.add   // []),
                  cap_drop:  (.securityContext.capabilities.drop  // [])
                }]
                +
                [.spec.initContainers[]? | {
                  name,
                  cap_add:   (.securityContext.capabilities.add   // []),
                  cap_drop:  (.securityContext.capabilities.drop  // [])
                }]
              )
            }
          | select(
              ([.containers[]?.cap_add[]?] | length) > 0
              or
              (
                # has capabilities block but does *not* drop ALL
                ([.containers[]?.cap_drop[]?] | length) > 0
                and
                (([.containers[]?.cap_drop[]?] | index("ALL")) == null)
              )
            )
          | "NAMESPACE: \(.ns)\nPOD: \(.pod)\n" +
            (
              .containers[]
              | "  container: \(.name)\n" +
                "    add:  \(.cap_add | join(\", \"))\n" +
                "    drop: \(.cap_drop | join(\", \"))\n"
            )
          + "---"
        '

        echo
        echo "=== 3) Deployments/DaemonSets/StatefulSets with capabilities in their pod templates ==="
        echo

        for kind in deployment daemonset statefulset; do
          echo "# ${kind^}s with capabilities configured:"
          kubectl get "$kind" -A -o json | jq -r "
            .items[]
            | {
                kind: \"${kind^}\",
                ns: .metadata.namespace,
                name: .metadata.name,
                containers: (
                  [.spec.template.spec.containers[]? | {
                    name,
                    cap_add:   (.securityContext.capabilities.add   // []),
                    cap_drop:  (.securityContext.capabilities.drop  // [])
                  }]
                  +
                  [.spec.template.spec.initContainers[]? | {
                    name,
                    cap_add:   (.securityContext.capabilities.add   // []),
                    cap_drop:  (.securityContext.capabilities.drop  // [])
                  }]
                )
              }
            | select(
                ([.containers[]?.cap_add[]?] | length) > 0
                or
                (
                  ([.containers[]?.cap_drop[]?] | length) > 0
                  and
                  (([.containers[]?.cap_drop[]?] | index(\"ALL\")) == null)
                )
              )
            | \"NAMESPACE: \(.ns)\nKIND: \(.kind)\nNAME: \(.name)\n\" +
              (
                .containers[]
                | \"  container: \(.name)\n\" +
                  \"    add:  \(.cap_add | join(\", \"))\n\" +
                  \"    drop: \(.cap_drop | join(\", \"))\n\"
              )
            + \"---\"
          "
          echo
        done

        echo "=== 4) Interpretation ==="
        cat <<'EOF'
        Problematic output to review:

        - Any pod or workload where:
          * 'add' lists one or more capabilities (e.g. NET_ADMIN, SYS_ADMIN), OR
          * 'drop' does not contain 'ALL' (i.e., capabilities are not fully dropped).

        From the benchmark perspective, namespaces that run applications which do NOT need
        Linux capabilities should:
          - Have no pods/workloads in the reports above, and
          - Be governed by a policy (e.g. PSP, or equivalent admission policy) that forbids
            admission of containers unless they drop ALL capabilities.

        Use the namespace information in the reports to decide where to tighten policy,
        and which workloads may need exceptions because they legitimately require capabilities.
        EOF
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>

### Additional Reading:

* [https://www.nccgroup.trust/uk/our-research/abusing-privileged-and-unprivileged-linux-containers/](https://www.nccgroup.trust/uk/our-research/abusing-privileged-and-unprivileged-linux-containers/)
