> ## 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 Admission Of Containers With NET_RAW Capability

### More Info:

Do not generally permit containers with the potentially dangerous NET\_RAW capability.

### Risk Level

Medium

### Address

Security

### Compliance Standards

* CIS Kubernetes

### Triage and Remediation

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

    <AccordionGroup>
      <Accordion title="Manual Steps" defaultOpen="true">
        1. **Identify namespaces with user workloads and existing Pod Security controls**
           * Run on: any machine with kubectl access
           ```bash theme={null}
           kubectl get ns
           kubectl get ns -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.metadata.labels}{"\n"}{end}'
           kubectl get psp 2>/dev/null || echo "No PodSecurityPolicies found"
           kubectl get validatingwebhookconfigurations.admissionregistration.k8s.io
           kubectl get mutatingwebhookconfigurations.admissionregistration.k8s.io
           ```
           * Decide which namespaces are for user workloads and require explicit restriction.

        2. **Review current use of NET\_RAW in existing workloads**
           * Run on: any machine with kubectl access
           ```bash theme={null}
           # List pods that explicitly add NET_RAW
           kubectl get pods --all-namespaces -o json \
             | jq -r '
               .items[] |
               .metadata.namespace as $ns |
               .metadata.name as $pod |
               (.spec.containers[]?, .spec.initContainers[]?) as $c |
               ($c.securityContext.capabilities.add[]? // empty) as $cap |
               select($cap == "NET_RAW") |
               [$ns, $pod, $c.name, $cap] | @tsv
             '

           # List pods that drop all capabilities (good baseline)
           kubectl get pods --all-namespaces -o json \
             | jq -r '
               .items[] |
               .metadata.namespace as $ns |
               .metadata.name as $pod |
               (.spec.containers[]?, .spec.initContainers[]?) as $c |
               select($c.securityContext.capabilities.drop[]? == "ALL") |
               [$ns, $pod, $c.name] | @tsv
             '
           ```
           * For each workload using NET\_RAW, confirm whether it is strictly required for functionality.

        3. **Decide the policy mechanism to enforce NET\_RAW restriction per namespace**
           * If using built-in Pod Security Admission (PSA):
             ```bash theme={null}
             kubectl get ns --show-labels
             ```
             Decide whether to move namespaces to `restricted` or keep `baseline` and add an admission policy for NET\_RAW.
           * If using OPA Gatekeeper or Kyverno, decide which policy engine to use or extend.

        4. **Review or define namespace-level policies that deny NET\_RAW**
           * Example Gatekeeper audit (if Gatekeeper installed):
             ```bash theme={null}
             kubectl get k8sallowedcapabilities.constraints.gatekeeper.sh -A
             kubectl get k8spspallowedcapabilities.constraints.gatekeeper.sh -A
             ```
           * Example Kyverno audit (if Kyverno installed):
             ```bash theme={null}
             kubectl get clusterpolicy,policy -A
             ```
           * For each user-workload namespace, ensure there is a policy that either forbids `NET_RAW` entirely or allows it only for explicitly named workloads. If missing, plan to create such a policy (e.g., Gatekeeper Constraint or Kyverno Policy) targeting that namespace.

        5. **Tighten or add securityContext in manifests for required exceptions**
           * For workloads that legitimately need NET\_RAW, explicitly declare and isolate the requirement in their manifests so policies can allow only those:
           ```bash theme={null}
           # Example: inspect a specific deployment manifest
           kubectl get deploy -n <namespace> <deployment-name> -o yaml
           ```
           * Ensure manifests for workloads that do *not* need NET\_RAW either omit capability additions or explicitly drop all capabilities:
           ```yaml theme={null}
           securityContext:
             allowPrivilegeEscalation: false
             capabilities:
               drop: ["ALL"]
           ```

        6. **Verify that admission is now minimized for NET\_RAW**
           * After updating policies and manifests, test admission in a user-workload namespace that should be restricted:
           ```bash theme={null}
           cat <<'EOF' | kubectl apply -n <user-namespace> -f -
           apiVersion: v1
           kind: Pod
           metadata:
             name: net-raw-test-deny
           spec:
             containers:
             - name: c
               image: busybox
               command: ["sleep", "3600"]
               securityContext:
                 capabilities:
                   add: ["NET_RAW"]
           EOF
           ```
           * Confirm that this pod is rejected with an admission error referring to the policy (or, if allowed by design in a specific exception namespace, confirm that it is the only such namespace and that others are denied).
      </Accordion>

      <Accordion title="Using kubectl">
        ```bash theme={null}
        # 1. List all namespaces so you can decide which host user workloads
        # Run on: any machine with kubectl access
        kubectl get ns -o name
        ```

        A problem exists if you find namespaces that run user workloads but have no policy objects controlling capabilities (next steps).

        ***

        ```bash theme={null}
        # 2. For each user-workload namespace, list PodSecurityPolicies (if used)
        # Replace NAMESPACE with the target namespace
        kubectl get podsecuritypolicies.policy -o yaml
        ```

        Problem indicators:

        * PSPs exist that are referenced by your workloads’ ServiceAccounts (RBAC bindings), **and**:
          * `.spec.allowedCapabilities` includes `NET_RAW`, or
          * `.spec.defaultAddCapabilities` includes `NET_RAW`, or
          * `.spec.requiredDropCapabilities` does **not** include `NET_RAW` while other caps are restricted
        * Or: there is **no** PSP at all in a cluster where PSP is the intended control.

        ***

        ```bash theme={null}
        # 3. For each user-workload namespace, list local security policies
        # Run on: any machine with kubectl access

        # Pod Security admission labels on the namespace
        kubectl get ns NAMESPACE -o yaml

        # PodSecurityPolicy (legacy) references via RBAC (optional deeper check)
        kubectl get role,rolebinding,clusterrole,clusterrolebinding -n NAMESPACE -o yaml
        ```

        Problem indicators:

        * Namespace has no Pod Security admission labels (e.g. `pod-security.kubernetes.io/enforce`), so you rely only on ad‑hoc controls.
        * RBAC bindings grant access to permissive PSPs (from previous step) that allow `NET_RAW`.

        ***

        ```bash theme={null}
        # 4. Inspect PodSpecs in the namespace for explicit NET_RAW use
        # Run on: any machine with kubectl access

        # Current running Pods
        kubectl get pods -n NAMESPACE -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{range .spec.containers[*]}  {.name}{" capsAdd:"}{.securityContext.capabilities.add}{" capsDrop:"}{.securityContext.capabilities.drop}{"\n"}{end}{"\n"}{end}'

        # All workload controllers (Deployments, DaemonSets, etc.)
        kubectl get deploy,sts,ds,job,cronjob -n NAMESPACE -o yaml
        ```

        Problem indicators:

        * Any container shows `capsAdd:[NET_RAW ...]` or similar in `.securityContext.capabilities.add`.
        * Workload manifests define `securityContext.capabilities.add` including `NET_RAW`, or fail to drop it when your policy model expects explicit dropping.

        ***

        ```bash theme={null}
        # 5. Check for namespace-level defaulting via mutating/validating webhooks
        # Run on: any machine with kubectl access
        kubectl get mutatingwebhookconfigurations,validatingwebhookconfigurations -o yaml
        ```

        Problem indicators:

        * Webhooks that **add** `NET_RAW` to container capabilities.
        * Absence of any validating webhook that enforces dropping `NET_RAW` when your security model expects such enforcement.

        ***

        ```bash theme={null}
        # 6. If using Pod Security Admission (PSA), verify the effective level
        # Run on: any machine with kubectl access
        kubectl label ns NAMESPACE --list
        ```

        Problem indicators:

        * Namespace labels such as:
          * `pod-security.kubernetes.io/enforce=privileged`
          * or no `pod-security.kubernetes.io/*` labels at all
        * In these cases, containers may run with `NET_RAW` unless controlled by other mechanisms.

        ***

        ```bash theme={null}
        # 7. Spot-check a known sensitive namespace for an example Pod
        # Run on: any machine with kubectl access
        kubectl get pod PODNAME -n NAMESPACE -o yaml
        ```

        Problem indicators:

        * Under `spec.containers[].securityContext.capabilities.add`, `NET_RAW` is present without a strong, documented business justification.
        * There is no organizational pattern (annotations, labels, documentation) explaining why `NET_RAW` is required.
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        set -euo pipefail

        # This script inspects all namespaces for policies that restrict the NET_RAW capability.
        # It does NOT change anything; it only reports for review.

        echo "=== Cluster-wide NET_RAW admission review ==="
        echo

        echo "1) Namespaces and PodSecurity admission levels (if enabled)"
        echo "----------------------------------------------------------"
        kubectl get ns -o json | jq -r '
          .items[]
          | .metadata as $m
          | (
              $m.labels."pod-security.kubernetes.io/enforce",
              $m.labels."pod-security.kubernetes.io/warn",
              $m.labels."pod-security.kubernetes.io/audit"
            ) as $ps
          | [
              $m.name,
              $m.labels."pod-security.kubernetes.io/enforce",
              $m.labels."pod-security.kubernetes.io/enforce-version",
              $m.labels."pod-security.kubernetes.io/warn",
              $m.labels."pod-security.kubernetes.io/warn-version",
              $m.labels."pod-security.kubernetes.io/audit",
              $m.labels."pod-security.kubernetes.io/audit-version"
            ]
          | @tsv' \
          | awk 'BEGIN {
              OFS="\t";
              print "NAMESPACE","ENFORCE","ENFORCE_VER","WARN","WARN_VER","AUDIT","AUDIT_VER"
            } {print}'

        echo
        echo "Problem indication for step 1:"
        echo "- Namespaces running user workloads that are NOT labeled with at least ENFORCE=baseline or ENFORCE=restricted"
        echo "  may allow NET_RAW unless another policy (PSP/Gatekeeper/PodSecurityPolicy replacement) blocks it."
        echo

        echo "2) PodSecurityPolicies (if still present) and their NET_RAW rules"
        echo "-----------------------------------------------------------------"
        if kubectl api-resources | grep -q "^podsecuritypolicies.extensions" || \
           kubectl api-resources | grep -q "^podsecuritypolicies.policy"; then
          kubectl get podsecuritypolicies -o json | jq -r '
            .items[]
            | .metadata.name as $name
            | .spec as $s
            | $s.requiredDropCapabilities as $reqDrop
            | $s.allowedCapabilities as $allowed
            | $s.defaultAddCapabilities as $defaultAdd
            | [
                $name,
                (if ($reqDrop // []) | index("NET_RAW") then "YES" else "NO" end),
                (if ($allowed // []) | index("NET_RAW") then "YES" else "NO" end),
                (if ($defaultAdd // []) | index("NET_RAW") then "YES" else "NO" end)
              ]
            | @tsv' \
            | awk 'BEGIN {
                OFS="\t";
                print "PSP","REQUIRES_DROP_NET_RAW","ALLOWS_NET_RAW","DEFAULT_ADDS_NET_RAW"
              } {print}'
        else
          echo "No PodSecurityPolicy API detected in this cluster."
        fi

        echo
        echo "Problem indication for step 2:"
        echo "- Any PSP that:"
        echo "  * does NOT require dropping NET_RAW (REQUIRES_DROP_NET_RAW=NO) AND"
        echo "  * either ALLOWS_NET_RAW=YES or DEFAULT_ADDS_NET_RAW=YES"
        echo "  indicates a risk that containers can keep or gain NET_RAW."
        echo

        echo "3) Gatekeeper/OPA or Kyverno-like policies mentioning NET_RAW (if installed)"
        echo "---------------------------------------------------------------------------"
        echo "# Gatekeeper/OPA constraints and templates referencing NET_RAW:"
        if kubectl api-resources | grep -qi 'constrainttemplate'; then
          kubectl get constrainttemplates -A -o yaml | grep -n --color=always -i 'NET_RAW' || \
            echo "No NET_RAW references found in ConstraintTemplates."
          echo
          kubectl get constraints -A -o yaml 2>/dev/null | grep -n --color=always -i 'NET_RAW' || \
            echo "No NET_RAW references found in Constraints."
        else
          echo "No Gatekeeper ConstraintTemplate API detected."
        fi

        echo
        echo "# Kyverno ClusterPolicies/Policies referencing NET_RAW:"
        if kubectl api-resources | grep -qi '^clusterpolicies.kyverno.io'; then
          kubectl get clusterpolicies -A -o yaml | grep -n --color=always -i 'NET_RAW' || \
            echo "No NET_RAW references found in Kyverno ClusterPolicies."
        fi
        if kubectl api-resources | grep -qi '^policies.kyverno.io'; then
          kubectl get policies -A -o yaml | grep -n --color=always -i 'NET_RAW' || \
            echo "No NET_RAW references found in Kyverno Policies."
        fi

        echo
        echo "Problem indication for step 3:"
        echo "- Absence of any admission policies (Gatekeeper/Kyverno or similar) that:"
        echo "  * explicitly require dropping NET_RAW, or"
        echo "  * forbid adding NET_RAW,"
        echo "  in namespaces without strict PodSecurity admission."
        echo

        echo "4) Workload specs that currently request or retain NET_RAW"
        echo "---------------------------------------------------------"
        echo "Scanning Pods, Deployments, StatefulSets, DaemonSets, Jobs, and CronJobs for NET_RAW..."
        echo

        resources=(
          "pods"
          "deployments.apps"
          "statefulsets.apps"
          "daemonsets.apps"
          "jobs.batch"
          "cronjobs.batch"
        )

        for r in "${resources[@]}"; do
          echo "== $r =="
          if ! kubectl get "$r" --all-namespaces >/dev/null 2>&1; then
            echo "  (resource type not found or not used)"
            echo
            continue
          fi

          kubectl get "$r" --all-namespaces -o json | jq -r '
            .items[]
            | .metadata as $m
            | .spec as $s
            | (
                if .kind=="Pod" then $s
                else
                  # handle controllers with pod templates
                  ( if $s.template then $s.template.spec else $s end )
                end
              ) as $pspec
            | ($pspec.containers // []) as $containers
            | ($pspec.initContainers // []) as $initContainers
            | ($pspec.ephemeralContainers // []) as $ephContainers
            | [$containers[], $initContainers[], $ephContainers[]]?
            | select(. != null)
            | .name as $cname
            | .securityContext as $csec
            | $pspec.securityContext as $psec
            | [
                $m.namespace,
                $m.name,
                .image,
                $cname,
                (
                  if ($csec.capabilities.drop // []) | index("NET_RAW")
                  then "YES"
                  else "NO"
                  end
                ),
                (
                  if ($csec.capabilities.add // []) | index("NET_RAW")
                  then "YES"
                  else "NO"
                  end
                ),
                (
                  if ($psec.capabilities.drop // []) | index("NET_RAW")
                  then "YES"
                  else "NO"
                  end
                ),
                (
                  if ($psec.capabilities.add // []) | index("NET_RAW")
                  then "YES"
                  else "NO"
                  end
                )
              ]
            | @tsv' 2>/dev/null \
            | awk 'BEGIN {
                OFS="\t";
                print "NAMESPACE","WORKLOAD_NAME","IMAGE","CONTAINER",
                      "CONTAINER_DROPS_NET_RAW","CONTAINER_ADDS_NET_RAW",
                      "POD_DROPS_NET_RAW","POD_ADDS_NET_RAW"
              } {print}'
          echo
        done

        echo "Problem indication for step 4:"
        echo "- Any line where:"
        echo "  * CONTAINER_ADDS_NET_RAW=YES or POD_ADDS_NET_RAW=YES  -> container explicitly gains NET_RAW."
        echo "  * CONTAINER_DROPS_NET_RAW=NO and POD_DROPS_NET_RAW=NO -> no explicit drop;"
        echo "    combined with weak PodSecurity/admission policy this may allow NET_RAW to be retained."
        echo
        echo "Review guidance:"
        echo "- Focus on user-workload namespaces that lack strict PodSecurity or other admission controls."
        echo "- In those namespaces, identify workloads with ADDS_NET_RAW=YES or that do not drop NET_RAW."
        echo "- Decide case-by-case whether NET_RAW is strictly required; if not, adjust manifests or add policies"
        echo "  (per-namespace admission controls) to require dropping NET_RAW or forbid adding it."
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>

### Additional Reading:

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