> ## 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 The NET_RAW Capability

### More Info:

The NET\_RAW capability allows crafting raw packets for spoofing and network attacks. Restrict its admission in workload namespaces.

### 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. **Identify workload namespaces and existing policies**
           * On any machine with kubectl access:
             ```bash theme={null}
             kubectl get ns
             kubectl get psp --all-namespaces 2>/dev/null || echo "No PodSecurityPolicy cluster resource"
             kubectl get psp 2>/dev/null -o yaml || true
             kubectl get psp --all-namespaces -o wide 2>/dev/null || true
             kubectl get ns --show-labels
             ```
           * Decide which namespaces contain user workloads (exclude kube-system, monitoring, logging, etc. unless users run apps there).

        2. **Review current use of NET\_RAW in running workloads**
           * On any machine with kubectl access, for each workload namespace (substitute the namespace name):
             ```bash theme={null}
             NAMESPACE=prod
             kubectl get pods -n "$NAMESPACE" -o json \
               | jq -r '.items[]
                 | .metadata.name as $p
                 | .spec.containers[]?
                 | select(.securityContext.capabilities.add[]? == "NET_RAW")
                 | "\($p) \(.name) uses NET_RAW"' 2>/dev/null
             kubectl get pods -n "$NAMESPACE" -o json \
               | jq -r '.items[]
                 | .metadata.name as $p
                 | .spec.initContainers[]?
                 | select(.securityContext.capabilities.add[]? == "NET_RAW")
                 | "\($p) init:\(.name) uses NET_RAW"' 2>/dev/null
             ```
           * Record which applications currently rely on NET\_RAW and confirm with the application owners whether it is truly required.

        3. **Review admission controls that could restrict NET\_RAW**
           * On any machine with kubectl access:
             ```bash theme={null}
             # Pod Security Admission (PSA) labels
             kubectl get ns --show-labels

             # Gatekeeper / Kyverno / other policy engines
             kubectl get constraints.constraints.gatekeeper.sh -A 2>/dev/null || true
             kubectl get cpolicies.kyverno.io -A 2>/dev/null || true
             kubectl get policies.policy -A 2>/dev/null || true

             # PodSecurityPolicy if still in use
             kubectl get psp -o yaml 2>/dev/null || true
             ```
           * For each mechanism you find, inspect whether it already forbids adding `NET_RAW` in workload namespaces (e.g., by disallowing `capabilities.add` or explicitly listing forbidden capabilities).

        4. **Decide namespace-by-namespace policy for NET\_RAW**
           * For each workload namespace, make an explicit decision:
             * **Forbidden**: no containers should ever use NET\_RAW.
             * **Exception-only**: NET\_RAW allowed only for tightly controlled workloads.
           * Document the decision with justification (e.g., “prod namespace: NET\_RAW forbidden; only network diagnostics namespace allows it”).

        5. **Implement or tighten policies to enforce the decision**
           * This is done by editing/adding Kubernetes policy objects (Pod Security Admission labels, Gatekeeper/Kyverno policies, or PodSecurityPolicy if present). There is no single command that applies to every cluster.
           * For the chosen mechanism, ensure policies for each workload namespace:
             * Reject pods that add `NET_RAW` unless they match an explicitly defined exception (e.g., label-based allowlist).
             * Apply policies to all relevant namespaces (via namespace labels, selectors, or target lists).
           * Use `kubectl apply -f <policy-file>.yaml` from any machine with kubectl access to create/update these policy objects.

        6. **Verify that NET\_RAW is effectively restricted**
           * On any machine with kubectl access, in a workload namespace that should disallow NET\_RAW, try to create a test pod:
             ```bash theme={null}
             cat <<'EOF' | kubectl apply -f -
             apiVersion: v1
             kind: Pod
             metadata:
               name: net-raw-test
               namespace: prod
             spec:
               containers:
               - name: test
                 image: busybox:1.36
                 command: ["sleep", "3600"]
                 securityContext:
                   capabilities:
                     add: ["NET_RAW"]
             EOF
             ```
           * Confirm that creation is **rejected** by the admission controls.
           * Re-run the inspection to ensure no admitted pods use NET\_RAW unexpectedly:
             ```bash theme={null}
             kubectl get pods -n prod -o json \
               | jq -r '.items[]
                 | .metadata.name as $p
                 | .spec.containers[]?
                 | select(.securityContext.capabilities.add[]? == "NET_RAW")
                 | "\($p) \(.name) uses NET_RAW"' 2>/dev/null
             ```
      </Accordion>

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

        #### 1. List all namespaces that may host user workloads

        Run on: any machine with `kubectl` access.

        ```sh theme={null}
        kubectl get namespaces -o custom-columns=NAME:.metadata.name \
          --no-headers | grep -vE '^(kube-system|kube-public|kube-node-lease)$'
        ```

        **What to look for:**\
        The resulting list are candidate “user” namespaces where you should expect admission controls (Pod Security Admission, OPA/Gatekeeper, Kyverno, PSP if still used, etc.) to prevent `NET_RAW`.

        ***

        #### 2. Check for existing Pod-level security controls per namespace

        ##### 2.1. Check Pod Security Admission labels (if PSA is in use)

        ```sh theme={null}
        kubectl get ns --show-labels | grep pod-security
        ```

        **Problem indication:**\
        Namespaces used for user workloads that:

        * Have no `pod-security.kubernetes.io/enforce` label, or
        * Are labeled `privileged` or an overly permissive level,\
          may allow pods with the `NET_RAW` capability unless another policy mechanism blocks it.

        ***

        ##### 2.2. List any PodSecurityPolicies (legacy PSP clusters only)

        ```sh theme={null}
        kubectl get podsecuritypolicies.policy -o wide
        ```

        Then, for each PSP:

        ```sh theme={null}
        kubectl get podsecuritypolicies.policy <psp-name> -o yaml
        ```

        **Problem indication:**\
        PSPs that:

        * Do not restrict `allowedCapabilities`, and
        * Do not list `NET_RAW` under `forbiddenSysctls`/capabilities-like controls (or otherwise constrain capabilities),\
          are likely to permit `NET_RAW`. Also check RBAC bindings to see which namespaces/pods can use such PSPs.

        ***

        ##### 2.3. Check common policy engines (if deployed)

        **Gatekeeper (OPA) constraints:**

        ```sh theme={null}
        kubectl get constraints.constraints.gatekeeper.sh -A
        kubectl get k8spspcapabilities.constraints.gatekeeper.sh -A 2>/dev/null
        ```

        Then inspect:

        ```sh theme={null}
        kubectl get k8spspcapabilities.constraints.gatekeeper.sh <constraint-name> -n <ns> -o yaml
        ```

        **Problem indication:**

        * No constraints limiting container capabilities, or
        * Constraints that do not mention `NET_RAW` in disallowed capabilities, or
        * Constraints not selecting the user namespaces.

        **Kyverno ClusterPolicies/Policies:**

        ```sh theme={null}
        kubectl get clusterpolicies.kyverno.io -o yaml
        kubectl get policies.kyverno.io -A -o yaml
        ```

        **Problem indication:**\
        Policies do not contain rules that deny or mutate away `NET_RAW`, or are not applied (via `match` / `exclude`) to user namespaces.

        ***

        #### 3. Identify pods/containers that currently request or add NET\_RAW

        > This is evidence gathering; existing pods may be noncompliant with your intended policy.

        ```sh theme={null}
        kubectl get pods -A -o json | \
          jq -r '
            .items[]
            | {ns: .metadata.namespace, pod: .metadata.name, spec: .spec}
            | . as $pod
            | ($pod.spec.containers + ($pod.spec.initContainers // []))[]
            | .name as $cname
            | {ns: $pod.ns, pod: $pod.pod, container: $cname, sc: .securityContext, psc: $pod.spec.securityContext}
            | select(
                (
                  (.psc.capabilities.add // []) + (.sc.capabilities.add // [])
                ) | index("NET_RAW")
              )
            | "\(.ns) \(.pod) \(.container)"'
        ```

        If `jq` is not available:

        ```sh theme={null}
        kubectl get pods -A -o yaml | \
          grep -E '^(  namespace:|  name:| *capabilities:| *add:| *- NET_RAW)' -n
        ```

        **Problem indication:**\
        Any line(s)/entries showing containers with:

        ```yaml theme={null}
        securityContext:
          capabilities:
            add:
              - NET_RAW
        ```

        either at the container level or via `pod.spec.securityContext.capabilities.add`. Those pods are using `NET_RAW` and should be reviewed to determine if the capability is truly required.

        ***

        #### 4. Check for Pod Security Standards violations (if PSA is enabled)

        > This does not directly “know” about `NET_RAW` but helps identify overly privileged pods.

        ```sh theme={null}
        kubectl auth reconcile -f /dev/null 2>&1 | grep -i 'pod-security'
        ```

        If your cluster exposes PSA events via audit annotations, you can inspect a sample pod:

        ```sh theme={null}
        kubectl get pod -n <user-namespace> -o yaml <pod-name> | \
          grep -i 'pod-security.kubernetes.io' -n
        ```

        **Problem indication:**

        * Namespaces or pods not being evaluated by PSA, or
        * Pods running effectively at `privileged` level without other compensating policies, which makes it more likely they can use `NET_RAW`.

        ***

        #### 5. Optional: Dry-run admission test (non-production namespace)

        Create a temporary test namespace:

        ```sh theme={null}
        kubectl create namespace net-raw-test
        ```

        Apply a pod that explicitly adds `NET_RAW`:

        ```sh theme={null}
        cat << 'EOF' | kubectl apply --dry-run=server -f -
        apiVersion: v1
        kind: Pod
        metadata:
          name: net-raw-test-pod
          namespace: net-raw-test
        spec:
          containers:
          - name: test
            image: busybox
            command: ["sleep", "3600"]
            securityContext:
              capabilities:
                add:
                - NET_RAW
        EOF
        ```

        **Problem indication:**

        * If the dry-run **succeeds** (“pod/net-raw-test-pod created (server dry run)”), there is currently no admission control in that namespace preventing `NET_RAW`.
        * If the dry-run **fails** with a validation/admission error referring to capabilities or policies, then some control is in place; review the error text to confirm it is specifically blocking `NET_RAW`.

        Clean up:

        ```sh theme={null}
        kubectl delete namespace net-raw-test
        ```
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        # Purpose: Report pods that request or add the NET_RAW capability anywhere in the cluster.
        # Runs on: any machine with kubectl access and current context pointing to the target cluster.

        set -euo pipefail

        # 1. List pods that explicitly ADD NET_RAW via securityContext.capabilities.add
        echo "=== Pods that explicitly ADD NET_RAW capability (pod- or container-level) ==="
        kubectl get pods --all-namespaces -o json | \
          jq -r '
            .items[]
            | {
                ns: .metadata.namespace,
                pod: .metadata.name,
                podCapsAdd: (.spec.securityContext.capabilities.add // [] | map(select(.=="NET_RAW"))),
                init: (
                  .spec.initContainers // [] |
                  map({
                    name: .name,
                    capsAdd: (.securityContext.capabilities.add // [] | map(select(.=="NET_RAW")))
                  }) |
                  map(select(.capsAdd|length>0))
                ),
                containers: (
                  .spec.containers // [] |
                  map({
                    name: .name,
                    capsAdd: (.securityContext.capabilities.add // [] | map(select(.=="NET_RAW")))
                  }) |
                  map(select(.capsAdd|length>0))
                )
              }
            | select(
                ((.podCapsAdd|length)>0)
                or ((.init|length)>0)
                or ((.containers|length)>0)
              )
            | "NAMESPACE=\(.ns) POD=\(.pod) " +
              "POD_CAPS_ADD=\(.podCapsAdd) " +
              "INIT_CONTAINERS=" +
                (if (.init|length)>0 then (.init|map("\(.name):\(.capsAdd)")|join(",")) else "none" end) +
              " CONTAINERS=" +
                (if (.containers|length)>0 then (.containers|map("\(.name):\(.capsAdd)")|join(",")) else "none" end)
          ' | sort || echo "jq not available or no matching pods found."

        echo
        # 2. List pods that use privileged or broad capabilities, which may implicitly allow raw sockets
        #    (for review – does NOT necessarily mean NET_RAW is in use, but these are higher risk)
        echo "=== Pods with privileged=true or ALL capabilities (for manual review of NET_RAW need) ==="
        kubectl get pods --all-namespaces -o json | \
          jq -r '
            .items[]
            | {
                ns: .metadata.namespace,
                pod: .metadata.name,
                podSC: .spec.securityContext,
                init: .spec.initContainers // [],
                containers: .spec.containers // []
              }
            | {
                ns,
                pod,
                privileged: (
                  [
                    (.podSC.privileged // false),
                    (init[]?.securityContext.privileged // false),
                    (containers[]?.securityContext.privileged // false)
                  ] | any
                ),
                allCaps: (
                  [
                    (.podSC.capabilities.add // []),
                    (.podSC.capabilities.drop // []),
                    (init[]?.securityContext.capabilities.add // []),
                    (init[]?.securityContext.capabilities.drop // []),
                    (containers[]?.securityContext.capabilities.add // []),
                    (containers[]?.securityContext.capabilities.drop // [])
                  ] | flatten | map(tostring) | map(ascii_upcase) | any(.=="ALL")
                )
              }
            | select(.privileged==true or .allCaps==true)
            | "NAMESPACE=\(.ns) POD=\(.pod) PRIVILEGED=\(.privileged) USES_ALL_CAPS=\(.allCaps)"
          ' | sort || echo "jq not available or no matching pods found."

        echo
        # 3. Summarize namespaces that currently admit NET_RAW (for policy targeting)
        echo "=== Namespaces where any pod adds NET_RAW (target these for admission policies) ==="
        kubectl get pods --all-namespaces -o json | \
          jq -r '
            .items[]
            | select(
                (
                  .spec.securityContext.capabilities.add // [] | index("NET_RAW")
                ) != null
                or (
                  [.spec.initContainers[]?.securityContext.capabilities.add // []] | flatten | index("NET_RAW")
                ) != null
                or (
                  [.spec.containers[]?.securityContext.capabilities.add // []] | flatten | index("NET_RAW")
                ) != null
              )
            | .metadata.namespace
          ' | sort -u || echo "jq not available or no matching namespaces found."
        ```

        **How to interpret the output**

        * Any line under **“Pods that explicitly ADD NET\_RAW capability”** indicates a **problem** for this control: those pods are being admitted with `NET_RAW` and should be reviewed; if not strictly required, they should be reconfigured to drop it and/or blocked by admission policy.
        * Lines under **“Pods with privileged=true or ALL capabilities”** are **high‑risk candidates**: they may effectively allow raw network operations even if `NET_RAW` is not explicitly listed. These require manual review to decide whether `NET_RAW` (or equivalent capability) is actually needed and whether to tighten security.
        * Namespaces listed under **“Namespaces where any pod adds NET\_RAW”** are **priority targets** for creating or tightening admission policies (e.g., PodSecurity, PodSecurityPolicies where still in use, or external admission controllers) to restrict `NET_RAW` for user workloads.
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
