Skip to main content

Minimize The Admission Of Containers With The NET_RAW

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​

Remediation​

Manual Steps
  1. Identify workload namespaces and existing policies

    • On any machine with kubectl access:
      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):
      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:
      # 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:
      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:
      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
Using kubectl

Using kubectl​

1. List all namespaces that may host user workloads​

Run on: any machine with kubectl access.

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)​
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)​
kubectl get podsecuritypolicies.policy -o wide

Then, for each PSP:

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:

kubectl get constraints.constraints.gatekeeper.sh -A
kubectl get k8spspcapabilities.constraints.gatekeeper.sh -A 2>/dev/null

Then inspect:

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:

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.

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:

kubectl get pods -A -o yaml | \
grep -E '^( namespace:| name:| *capabilities:| *add:| *- NET_RAW)' -n

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

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.

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:

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:

kubectl create namespace net-raw-test

Apply a pod that explicitly adds NET_RAW:

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:

kubectl delete namespace net-raw-test
Automation
#!/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.