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
Remediation
Manual Steps
-
Identify workload namespaces and existing policies
- On any machine with kubectl access:
kubectl get nskubectl get psp --all-namespaces 2>/dev/null || echo "No PodSecurityPolicy cluster resource"kubectl get psp 2>/dev/null -o yaml || truekubectl get psp --all-namespaces -o wide 2>/dev/null || truekubectl get ns --show-labels
- Decide which namespaces contain user workloads (exclude kube-system, monitoring, logging, etc. unless users run apps there).
- On any machine with kubectl access:
-
Review current use of NET_RAW in running workloads
- On any machine with kubectl access, for each workload namespace (substitute the namespace name):
NAMESPACE=prodkubectl 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/nullkubectl 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.
- On any machine with kubectl access, for each workload namespace (substitute the namespace name):
-
Review admission controls that could restrict NET_RAW
- On any machine with kubectl access:
# Pod Security Admission (PSA) labelskubectl get ns --show-labels# Gatekeeper / Kyverno / other policy engineskubectl get constraints.constraints.gatekeeper.sh -A 2>/dev/null || truekubectl get cpolicies.kyverno.io -A 2>/dev/null || truekubectl get policies.policy -A 2>/dev/null || true# PodSecurityPolicy if still in usekubectl get psp -o yaml 2>/dev/null || true
- For each mechanism you find, inspect whether it already forbids adding
NET_RAWin workload namespaces (e.g., by disallowingcapabilities.addor explicitly listing forbidden capabilities).
- On any machine with kubectl access:
-
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”).
- For each workload namespace, make an explicit decision:
-
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_RAWunless they match an explicitly defined exception (e.g., label-based allowlist). - Apply policies to all relevant namespaces (via namespace labels, selectors, or target lists).
- Reject pods that add
- Use
kubectl apply -f <policy-file>.yamlfrom any machine with kubectl access to create/update these policy objects.
-
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: v1kind: Podmetadata:name: net-raw-testnamespace: prodspec:containers:- name: testimage: busybox:1.36command: ["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
- On any machine with kubectl access, in a workload namespace that should disallow NET_RAW, try to create a test pod:
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/enforcelabel, or - Are labeled
privilegedor an overly permissive level,
may allow pods with theNET_RAWcapability 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_RAWunderforbiddenSysctls/capabilities-like controls (or otherwise constrain capabilities),
are likely to permitNET_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_RAWin 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_RAWbut 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
privilegedlevel without other compensating policies, which makes it more likely they can useNET_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_RAWand 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_RAWis not explicitly listed. These require manual review to decide whetherNET_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_RAWfor user workloads.