Minimize The Admission Containers With The Net Raw
More Info:
Do not generally permit containers with the potentially dangerous NET_RAW capability.
Risk Level
Medium
Address
Security
Compliance Standards
- APRA CPS 234 (Australia)
- BSI C5 (Germany)
- Brazil LGPD
- CCPA / CPRA (California)
- CIS Critical Security Controls v8
- CIS EKS
- 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
- Remediation
Remediation
Manual Steps
-
List current workload security settings (PSPs, PSP replacements, and policies)
Run on: any machine with kubectl access# PodSecurityPolicy (if still in use)kubectl get podsecuritypolicies.policy# Pod Security Admission (PSA) labels on namespaces (for newer clusters)kubectl get ns --show-labels | grep -E 'pod-security\.kubernetes\.io/(enforce|audit|warn)='# Common admission controllers: Gatekeeper, Kyverno, custom webhookskubectl get validatingwebhookconfigurations.admissionregistration.k8s.iokubectl get mutatingwebhookconfigurations.admissionregistration.k8s.iokubectl get cpol,pol,clustercpol -A 2>/dev/null || true -
Discover pods that currently have NET_RAW capability
Run on: any machine with kubectl accesskubectl get pods -A -o json \| jq -r '.items[]| .metadata as $m| (.spec.initContainers[]?, .spec.containers[]?) as $c| select(($c.securityContext.capabilities.add[]? // "") == "NET_RAW"or(($c.securityContext.capabilities.drop // []) | index("ALL") | not))| "\($m.namespace) \($m.name) \($c.name)"' | sort -uReview the output and identify which workloads:
- explicitly add
NET_RAW, or - fail to drop
NET_RAWby not droppingALL(and not droppingNET_RAWspecifically).
- explicitly add
-
Review pod and namespace security configuration for each affected workload
For each(namespace, pod, container)from step 2:# Show full pod speckubectl get pod -n <NAMESPACE> <POD_NAME> -o yaml# Show namespace labels / PSA configurationkubectl get ns <NAMESPACE> -o yaml# If PSP is used, see which PSP applies (cluster-specific process; as a proxy list PSPs)kubectl describe pod -n <NAMESPACE> <POD_NAME> | sed -n '1,80p'Manually check:
securityContext.capabilities.addforNET_RAWsecurityContext.capabilities.dropincludesALLor at leastNET_RAW- Whether any namespace or policy enforces a required drop of
NET_RAW/ALL.
-
Decide if each use of NET_RAW is strictly necessary
For each affected container, consult the owning team and application documentation to determine:- Is raw socket / packet crafting actually required (e.g., low-level networking, certain monitoring agents, specialized load balancers)?
- If yes, can the function be achieved using higher‑level networking APIs or sidecar patterns instead?
- If no, plan to remove
NET_RAWby:- eliminating it from
securityContext.capabilities.add, and/or - adding
NET_RAWorALLtosecurityContext.capabilities.drop.
- eliminating it from
-
Adjust policies/manifests to require dropping NET_RAW (or ALL) where safe
Based on step 4 decisions:- For namespace/workload manifests (Deployment/DaemonSet/Job/etc.), edit source manifests or Helm charts to:
- Remove any
NET_RAWfromsecurityContext.capabilities.add. - Add:
or at minimum:securityContext:capabilities:drop:- ALLsecurityContext:capabilities:drop:- NET_RAW
- Remove any
- For cluster-wide admission controls (PSP if still used, or equivalent OPA/Gatekeeper/Kyverno policies), configure rules that:
- Require
NET_RAWto be dropped, or - Forbid adding
NET_RAW, except for carefully scoped exceptions (namespaces/labels).
- Require
- For namespace/workload manifests (Deployment/DaemonSet/Job/etc.), edit source manifests or Helm charts to:
-
Verify that NET_RAW is no longer generally admitted
After redeploying updated workloads and/or policies, re-run:kubectl get pods -A -o json \| jq -r '.items[]| .metadata as $m| (.spec.initContainers[]?, .spec.containers[]?) as $c| select(($c.securityContext.capabilities.add[]? // "") == "NET_RAW"or(($c.securityContext.capabilities.drop // []) | index("ALL") | not))| "\($m.namespace) \($m.name) \($c.name)"' | sort -uConfirm:
- No general-purpose workloads appear in the list.
- Any remaining entries are explicitly reviewed and documented as justified exceptions.
Using kubectl
# 1. List all namespaces
# Run on: any machine with kubectl access
kubectl get ns -o name
Problem indication: None yet; this is just to scope the review.
# 2. List all PodSecurityPolicy objects (if the API is enabled)
# Run on: any machine with kubectl access
kubectl get podsecuritypolicy.policy -o yaml
Problem indication:
- PSPs missing
requiredDropCapabilitiescompletely. - PSPs with
requiredDropCapabilitiespresent but NOT includingNET_RAWorALL.
You are looking for sections like:
spec:
requiredDropCapabilities:
- NET_RAW
or
spec:
requiredDropCapabilities:
- ALL
PSPs whose requiredDropCapabilities list does not contain NET_RAW or ALL may allow containers with NET_RAW.
# 3. For each namespace, list pods and see what capabilities they actually have
# (this is evidence; enforcement is via PSP/PodSecurityPolicy-like controls)
# Run on: any machine with kubectl access
# Example: review all pods (can be large)
kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}{" "}{.metadata.name}{"\n"}{end}'
# For a specific namespace (replace <namespace>):
kubectl get pods -n <namespace> -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}'
Then inspect individual pods:
# Show full pod spec including securityContext and capabilities
# Run for any suspicious pod
kubectl get pod <pod-name> -n <namespace> -o yaml
Problem indication in pod YAML:
- At pod-level
securityContext:spec:securityContext:capabilities:add:- NET_RAW - Or at container-level:
spec:containers:- name: ...securityContext:capabilities:add:- NET_RAW
Any pod or container explicitly adding NET_RAW is a potential concern and requires human review to determine if it is justified.
# 4. Quickly search all pod specs for NET_RAW (evidence of usage)
# Run on: any machine with kubectl access
kubectl get pods -A -o yaml | grep -n "NET_RAW"
Problem indication:
- Any matches show pods or containers declaring
NET_RAWin their capabilities. - Each occurrence should be reviewed to decide whether
NET_RAWis truly required.
# 5. Check for namespace-level Pod Security (if applicable) that might allow NET_RAW
# Run on: any machine with kubectl access
kubectl get ns -o jsonpath='{range .items[*]}{.metadata.name}{" "}{.metadata.labels}{"\n"}{end}'
Problem indication:
- Namespaces labeled with privileged or unrestricted policies (for example,
pod-security.kubernetes.io/enforce=privilegedor similar) can make it easier for workloads to useNET_RAWwithout restriction. - These namespaces require closer review of workloads using the checks above.
Use these commands to collect evidence. Determining whether and where to forbid NET_RAW (e.g. via PodSecurityPolicy or other admission controls) requires human judgment based on application needs and acceptable risk.
Automation
#!/usr/bin/env bash
# Report pods/containers that can use NET_RAW capability (add or not dropped)
set -euo pipefail
# REQUIREMENTS:
# - Run on any machine with kubectl access and correct KUBECONFIG
# - kubectl 1.14+ with JSONPath support
echo "=== Scanning all pods/containers for NET_RAW capability exposure ===" >&2
# 1. List pods that explicitly ADD NET_RAW in securityContext.capabilities.add
echo
echo "== Pods with containers that explicitly ADD NET_RAW =="
kubectl get pods --all-namespaces -o json \
| jq -r '
.items[]
| {
ns: .metadata.namespace,
pod: .metadata.name,
containers: (
(.spec.containers + (.spec.initContainers // []))
| map(
{
name: .name,
addCaps: (.securityContext.capabilities.add // [] | map(. // ""))
}
)
)
}
| {
ns,
pod,
containers: (
.containers
| map(select(.addCaps | index("NET_RAW")))
)
}
| select(.containers | length > 0)
| [
"NAMESPACE=" + .ns,
"POD=" + .pod,
"CONTAINER(S)=" + (.containers | map(.name) | join(",")),
"ADDED_CAPS=" + (.containers | map(.addCaps | join(",")) | join(" | "))
]
| join(" | ")
' 2>/dev/null || {
echo "ERROR: This script requires 'jq' on PATH." >&2
exit 1
}
# 2. List pods where NET_RAW is NOT in drop list and there is some capability use
# This surfaces containers that might retain NET_RAW by omission
echo
echo "== Pods with capabilities configured but NET_RAW is NOT in drop list =="
kubectl get pods --all-namespaces -o json \
| jq -r '
.items[]
| {
ns: .metadata.namespace,
pod: .metadata.name,
containers: (
(.spec.containers + (.spec.initContainers // []))
| map(
{
name: .name,
addCaps: (.securityContext.capabilities.add // [] | map(. // "")),
dropCaps: (.securityContext.capabilities.drop // [] | map(. // ""))
}
)
)
}
| {
ns,
pod,
containers: (
.containers
| map(
select(
# Only consider containers that touch capabilities at all
((.addCaps | length) > 0 or (.dropCaps | length) > 0)
# AND do not explicitly drop NET_RAW nor ALL
and ((.dropCaps | index("NET_RAW")) | not)
and ((.dropCaps | index("ALL")) | not)
)
)
)
}
| select(.containers | length > 0)
| [
"NAMESPACE=" + .ns,
"POD=" + .pod,
"CONTAINER(S)=" + (.containers | map(.name) | join(",")),
"ADD_CAPS=" + (.containers | map(.addCaps | join(",")) | join(" | ")),
"DROP_CAPS=" + (.containers | map(.dropCaps | join(",")) | join(" | "))
]
| join(" | ")
'
# 3. (Optional) List any PodSecurityPolicies that DO NOT drop NET_RAW or ALL
# Only relevant if PSP is still enabled in your cluster
echo
echo "== PodSecurityPolicies that do NOT require dropping NET_RAW or ALL (if PSP is enabled) =="
if kubectl get podsecuritypolicies.policy >/dev/null 2>&1; then
kubectl get podsecuritypolicies.policy -o json \
| jq -r '
.items[]
| {
name: .metadata.name,
drop: (.spec.requiredDropCapabilities // [] | map(. // ""))
}
| select(
# PSPs that do NOT include NET_RAW and do NOT include ALL
((.drop | index("NET_RAW")) | not)
and ((.drop | index("ALL")) | not)
)
| "PSP=" + .name + " | requiredDropCapabilities=" + (.drop | join(","))
'
else
echo "No PodSecurityPolicies found or PSP API disabled; skip PSP check." >&2
fi
echo
echo "=== Interpretation ==="
cat <<'EOF'
- Any line under "Pods with containers that explicitly ADD NET_RAW" indicates a clear problem:
those containers are explicitly granted the NET_RAW capability.
- Any line under
"Pods with capabilities configured but NET_RAW is NOT in drop list"
is a potential problem:
these containers manipulate capabilities but do not explicitly drop NET_RAW
(or ALL), so you must review if their effective capabilities include NET_RAW.
- Any PSP listed under
"PodSecurityPolicies that do NOT require dropping NET_RAW or ALL"
should be reviewed: benchmark guidance expects requiredDropCapabilities
to include NET_RAW or ALL.
This script does NOT automatically fix anything; use it to identify and review
workloads and policies that might violate the requirement to drop NET_RAW.
EOF