> ## 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 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 GKE
* 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. **List all pods and identify capability usage (any machine with kubectl access)**
           ```bash theme={null}
           kubectl get pods -A -o json | jq -r '
             .items[] |
             .metadata.namespace as $ns |
             .metadata.name as $pod |
             .spec.containers[]? as $c |
             {
               ns: $ns,
               pod: $pod,
               container: $c.name,
               addCaps: ($c.securityContext.capabilities.add // []),
               dropCaps: ($c.securityContext.capabilities.drop // [])
             } |
             select((.addCaps | length) > 0 or (.dropCaps | length) > 0) |
             "\(.ns)\t\(.pod)\t\(.container)\tadd=\(.addCaps)\tdrop=\(.dropCaps)"'
           ```
           Save the output. It shows which containers explicitly add or drop capabilities by namespace.

        2. **Identify candidate namespaces that do not require Linux capabilities (any machine with kubectl access)**
           * From step 1 output, list namespaces that:
             * Have no entries at all (no pods declaring capabilities), or
             * Only have containers that already drop all capabilities (e.g. `drop=["ALL"]`) and do not add any.
           * For each such namespace, review the workloads and confirm with application owners that they do not need extra Linux capabilities (no low‑level networking, raw sockets, mounting filesystems, etc.).

        3. **Confirm no implicit capability dependencies (any machine with kubectl access)**\
           For each candidate namespace from step 2, inspect the deployments/statefulsets/daemonsets to ensure they are not relying on implicit default capabilities:
           ```bash theme={null}
           # Example for deployments; repeat for statefulsets/daemonsets as needed
           kubectl get deploy -n <NAMESPACE> -o yaml | grep -nA5 -E 'securityContext|capabilit'
           ```
           If any application is uncertain, treat it as requiring capabilities and exclude the namespace from enforcement until tested.

        4. **Design and define a Pod Security Policy (or equivalent) that forbids capabilities (any machine with kubectl access)**\
           If your cluster still supports PodSecurityPolicy, create a PSP manifest that requires all capabilities to be dropped and forbids adding any; for example, save as `/tmp/psp-drop-all-capabilities.yaml` and edit appropriately:
           ```yaml theme={null}
           apiVersion: policy/v1beta1
           kind: PodSecurityPolicy
           metadata:
             name: drop-all-capabilities
           spec:
             privileged: false
             allowPrivilegeEscalation: false
             requiredDropCapabilities:
               - ALL
             allowedCapabilities: []
             volumes:
               - '*'
             hostNetwork: false
             hostIPC: false
             hostPID: false
             runAsUser:
               rule: 'RunAsAny'
             seLinux:
               rule: 'RunAsAny'
             fsGroup:
               rule: 'RunAsAny'
             supplementalGroups:
               rule: 'RunAsAny'
           ```
           Apply it and create appropriate RBAC bindings for the service accounts in candidate namespaces:
           ```bash theme={null}
           kubectl apply -f /tmp/psp-drop-all-capabilities.yaml

           kubectl create clusterrole psp:drop-all-capabilities \
             --verb=use \
             --resource=podsecuritypolicies.policy \
             --resource-name=drop-all-capabilities

           kubectl create rolebinding psp:drop-all-capabilities \
             --clusterrole=psp:drop-all-capabilities \
             --serviceaccount=<NAMESPACE>:<SERVICE_ACCOUNT> \
             -n <NAMESPACE>
           ```
           If PSP is not available, use your platform’s equivalent (e.g., Pod Security Admission `restricted` level, Gatekeeper/Kyverno policies) to enforce “no added capabilities and drop ALL” for those namespaces.

        5. **Test workload behavior under the new restriction (any machine with kubectl access)**
           * Roll out or restart the workloads in each enforced namespace:
             ```bash theme={null}
             kubectl rollout restart deploy -n <NAMESPACE>
             ```
           * Monitor for failures indicating missing capabilities:
             ```bash theme={null}
             kubectl get pods -n <NAMESPACE>
             kubectl logs -n <NAMESPACE> <POD_NAME> <CONTAINER_NAME>
             ```
           * If any application fails due to capability restrictions, either:
             * Adjust policy narrowly to allow only the minimal required capability for that namespace, or
             * Remove that namespace from enforcement and document the justified requirement.

        6. **Re-verify capability usage to confirm minimization (any machine with kubectl access)**\
           Re-run the evidence command from step 1:
           ```bash theme={null}
           kubectl get pods -A -o json | jq -r '
             .items[] |
             .metadata.namespace as $ns |
             .metadata.name as $pod |
             .spec.containers[]? as $c |
             {
               ns: $ns,
               pod: $pod,
               container: $c.name,
               addCaps: ($c.securityContext.capabilities.add // []),
               dropCaps: ($c.securityContext.capabilities.drop // [])
             } |
             select((.addCaps | length) > 0 or (.dropCaps | length) > 0) |
             "\(.ns)\t\(.pod)\t\(.container)\tadd=\(.addCaps)\tdrop=\(.dropCaps)"'
           ```
           Confirm that in the namespaces where you decided capabilities are not required, no containers are admitted with added capabilities and that policies enforce dropping all capabilities. Document any exceptions and their justification.
      </Accordion>

      <Accordion title="Using kubectl">
        ```bash theme={null}
        # 1) List all namespaces
        # Run on: any machine with kubectl access
        kubectl get namespaces -o name
        ```

        Review which namespaces are expected to run security-sensitive workloads. For each namespace you care about, run:

        ```bash theme={null}
        # 2) List all pods in a namespace with their securityContext
        # Replace <namespace> with the target namespace name
        kubectl get pods -n <namespace> -o yaml \
          | sed -n '/containers:/,/^status:/p' \
          | sed -n '/- name:/,/resources:/p'
        ```

        Problem indication:

        * Under `securityContext.capabilities`, you see `add:` entries (e.g. `NET_ADMIN`, `SYS_ADMIN`, etc.).
        * No `drop: ["ALL"]` or equivalent is present for containers that do not truly need capabilities.

        For a more targeted view, list all pods in a namespace that define capabilities:

        ```bash theme={null}
        kubectl get pods -n <namespace> -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{range .spec.containers[*]}{"  "}{.name}{" -> "}{.securityContext.capabilities}{"\n"}{end}{"\n"}{end}'
        ```

        Problem indication:

        * Any container showing non-empty `add` entries or missing `drop:["ALL"]` in a namespace where workloads should not need capabilities.

        To see what policies (if any) might be constraining capabilities, inspect PodSecurityPolicy (if used) or newer controls (Pod Security Standards via labels):

        ```bash theme={null}
        # 3) Check for PodSecurityPolicy objects (legacy, if enabled)
        kubectl get podsecuritypolicies.policy

        # Inspect each PSP for capability rules
        kubectl get podsecuritypolicies.policy <psp-name> -o yaml
        ```

        Problem indication in PSP:

        * `spec.requiredDropCapabilities` does not include `ALL`.
        * `spec.allowedCapabilities` is broad (e.g. `["*"]`) or contains powerful capabilities, and this PSP is bound (via RBAC) to namespaces that should not allow capabilities.

        If using Pod Security Standards (admission via namespace labels):

        ```bash theme={null}
        # 4) Show Pod Security labels on namespaces
        kubectl get ns --show-labels | grep 'pod-security.kubernetes.io/'
        ```

        Problem indication:

        * Namespaces that should be strict have labels like:
          * `pod-security.kubernetes.io/enforce=privileged` or `baseline`
          * or no `pod-security.kubernetes.io/enforce` label at all.

        For individual workloads that may override namespace defaults, inspect their specs:

        ```bash theme={null}
        # 5) Check deployments (and similar controllers) for capabilities in a namespace
        kubectl get deploy -n <namespace> -o yaml \
          | sed -n '/containers:/,/strategy:/p'
        ```

        Problem indication:

        * Under each container’s `securityContext.capabilities`, presence of `add` capabilities and absence of `drop: ["ALL"]` in workloads that do not need them.

        Verification after any policy changes (manual, via manifests or admission config):

        ```bash theme={null}
        # Re-run checks to confirm current state
        kubectl get pods -n <namespace> -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{range .spec.containers[*]}{"  "}{.name}{" -> "}{.securityContext.capabilities}{"\n"}{end}{"\n"}{end}'

        kubectl get podsecuritypolicies.policy -o yaml
        kubectl get ns --show-labels | grep 'pod-security.kubernetes.io/'
        ```

        You must then decide, based on application requirements, which capabilities (if any) are actually needed and where policies should enforce dropping all capabilities. Kubectl cannot make that decision automatically.
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        #
        # Report pods and (Cluster)PodSecurityPolicies that allow Linux capabilities
        # Run on: any machine with kubectl access
        # Requires: kubectl, jq
        set -euo pipefail

        echo "=== 1) Namespaces and pods using container securityContext.capabilities ==="
        echo "NOTE: Focus on namespaces that should NOT need extra capabilities."

        kubectl get pods --all-namespaces -o json \
          | jq -r '
            .items[]
            | . as $pod
            | (
                ($pod.spec.containers // [])
                + ($pod.spec.initContainers // [])
              )[]
            | select(.securityContext.capabilities != null)
            | (
                $pod.metadata.namespace   as $ns
              | $pod.metadata.name        as $podname
              | .name                     as $cname
              | .securityContext.capabilities.add   // [] as $add
              | .securityContext.capabilities.drop  // [] as $drop
              | [$ns,$podname,$cname,($add|join("|")),($drop|join("|"))]
              | @tsv
            )
          ' \
          | awk 'BEGIN {
                   OFS="\t";
                   print "NAMESPACE","POD","CONTAINER","CAP_ADD","CAP_DROP"
                 }1' \
          | column -t

        echo
        echo "=== 2) PodSecurityPolicies (if any) and their capability rules ==="
        if kubectl api-resources | grep -q '^podsecuritypolicies'; then
          kubectl get podsecuritypolicies.policy -o json \
            | jq -r '
              .items[]
              | .metadata.name as $name
              | .spec.privileged as $priv
              | (.spec.requiredDropCapabilities // []) as $reqDrop
              | (.spec.allowedCapabilities // []) as $allowed
              | (.spec.defaultAddCapabilities // []) as $defaultAdd
              | [$name,
                 $priv,
                 ($reqDrop|join("|")),
                 ($allowed|join("|")),
                 ($defaultAdd|join("|"))
                ]
              | @tsv
            ' \
            | awk 'BEGIN {
                     OFS="\t";
                     print "PSP","PRIVILEGED","REQUIRED_DROP","ALLOWED_CAPS","DEFAULT_ADD_CAPS"
                   }1' \
            | column -t
        else
          echo "No PodSecurityPolicy API found in the cluster."
        fi

        echo
        echo "=== 3) Namespaces and applied Pod Security admission labels (if any) ==="
        echo "Relevant labels: pod-security.kubernetes.io/enforce, audit, warn"
        kubectl get ns --show-labels \
          | awk 'NR==1 || /pod-security.kubernetes.io/'

        echo
        echo "=== INTERPRETING THE OUTPUT ==="
        cat <<'EOF'
        Section 1 (pods with capabilities):
        - A potential problem is indicated when:
          - CAP_ADD column is non-empty, especially for high-privilege caps (e.g. NET_ADMIN, SYS_ADMIN, SYS_PTRACE).
          - CAP_DROP does not include ALL, or is empty, in namespaces where workloads do not need extra capabilities.
        - Focus first on:
          - Application namespaces (not kube-system or system add-ons) where CAP_ADD is set.
          - Namespaces that should be “locked down” but have many CAP_ADD entries.

        Section 2 (PodSecurityPolicies):
        - A potential problem is indicated when:
          - PRIVILEGED is true for PSPs used by regular application namespaces.
          - ALLOWED_CAPS is non-empty or contains ALL.
          - REQUIRED_DROP does not contain ALL for PSPs intended to strictly forbid capabilities.

        Section 3 (Pod Security admission labels):
        - A potential gap is indicated when:
          - Application namespaces do not have enforce-level labels set to a restrictive level (e.g. enforce=restricted).
          - There is no policy or label mechanism tied to capability restrictions.

        Use these reports to decide, per namespace:
        - Which workloads can safely drop all capabilities.
        - Where a stricter admission policy (e.g. PSP equivalent / Pod Security admission / OPA/Gatekeeper) should be applied to forbid capabilities for pods that do not need them.

        There is no fully automated fix: each flagged workload must be reviewed with its owner
        to confirm whether capabilities are actually required.
        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/)
