Minimize The Admission Of 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 GKE
- 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
-
On any machine with kubectl access, list all namespaces and current pod security configuration to understand what’s enforcing capabilities today:
kubectl get nskubectl get pspkubectl get psp -o yamlkubectl get podsecuritypolicies.policy -o yamlkubectl get ns --show-labelsIf PSP is disabled (no PSP objects or admission plugin disabled), note that and proceed to step 4 (you’ll need another enforcement mechanism such as Pod Security Admission or a 3rd‑party policy engine).
-
Still on a kubectl machine, identify which service accounts / namespaces currently use PSPs that do not drop NET_RAW:
# PSPs that do not require dropping NET_RAW or ALLkubectl get psp -o jsonpath='{range .items[?(!(@.spec.requiredDropCapabilities))]}{.metadata.name}{"\n"}{end}'kubectl get psp -o json | jq -r '.items[]| select((.spec.requiredDropCapabilities // []) | index("NET_RAW") | notand (.spec.requiredDropCapabilities // []) | index("ALL") | not)| .metadata.name'Review any associated RBAC bindings to see which subjects can use these PSPs:
kubectl get role,clusterrole,rolebinding,clusterrolebinding -A -o yaml | grep -B5 -A5 "use" | grep -B10 -A10 "podsecuritypolicies" -
For representative workloads (especially in high‑risk namespaces like default, kube-system, and any user application namespaces), inspect pod specs to see actual capability usage:
# Pods that explicitly add NET_RAWkubectl get pods -A -o json | jq -r '.items[]| select(([.spec.containers[], (.spec.initContainers // [])[]?][]| select(.securityContext.capabilities.add != null)| select(.securityContext.capabilities.add[] | contains("NET_RAW"))) != null)| "\(.metadata.namespace)/\(.metadata.name)"'# Pods that do not explicitly drop NET_RAW or ALLkubectl get pods -A -o json | jq -r '.items[]| select(([.spec.containers[], (.spec.initContainers // [])[]?][]| select(.securityContext.capabilities.drop != null)| select((.securityContext.capabilities.drop[] | contains("NET_RAW")) or(.securityContext.capabilities.drop[] | contains("ALL")))) == null)| "\(.metadata.namespace)/\(.metadata.name)"'Use this list to talk with application owners and determine whether NET_RAW is actually required for any workload.
-
Decide on a policy approach per namespace:
- If PSP is available: design one or more PSPs that set:
or:spec:requiredDropCapabilities:- NET_RAWThen update RBAC so that only tightly‑controlled subjects can use any PSPs that allow NET_RAW (if such PSPs are truly necessary).spec:requiredDropCapabilities:- ALL
- If PSP is not available: implement equivalent restrictions via your cluster’s policy mechanism (e.g., Pod Security Admission with
restrictedprofile and custom policies, or OPA/Gatekeeper/Kyverno) and ensure they reject pods that add NET_RAW and/or do not drop it.
- If PSP is available: design one or more PSPs that set:
-
Apply updated policies/manifests on a kubectl machine, in a staging environment first, then production. Coordinate with application teams for any namespaces that truly require NET_RAW and document explicit exceptions (namespaces, service accounts, and reasons). Where NET_RAW is required, prefer:
- A dedicated namespace
- Dedicated service accounts
- A narrowly‑scoped policy/PSP granting NET_RAW only to those workloads
-
Verify the effective state matches your intent:
# Confirm PSP or equivalent policy contains requiredDropCapabilities NET_RAW or ALLkubectl get psp -o yaml | grep -A3 "requiredDropCapabilities"# Confirm no unexpected pods can run with NET_RAWkubectl get pods -A -o json | jq -r '.items[]| select(([.spec.containers[], (.spec.initContainers // [])[]?][]| select(.securityContext.capabilities.add != null)| select(.securityContext.capabilities.add[] | contains("NET_RAW"))) != null)| "\(.metadata.namespace)/\(.metadata.name)"'For each remaining pod with NET_RAW, ensure it is covered by a documented, approved exception and that policies prevent any other workload from acquiring NET_RAW.
Using kubectl
# 1) List all PodSecurityPolicies (PSPs) and see if any drop NET_RAW
# Run on: any machine with kubectl access
kubectl get podsecuritypolicies.policy -o yaml
Review each PSP’s .spec.requiredDropCapabilities:
- Potential problem indicators:
requiredDropCapabilitiesis missing or empty.requiredDropCapabilitiesdoes not containNET_RAWorALL.- PSPs used by untrusted workloads allow running without dropping
NET_RAW.
# 2) Identify which PSPs are actually usable in each namespace
# (via RBAC bindings referencing them)
# Run on: any machine with kubectl access
kubectl get clusterrole,clusterrolebinding,role,rolebinding -A -o yaml
In the output, look for RBAC rules that reference podsecuritypolicies.policy in .rules[].resources and see:
- Which PSP names appear in
.rules[].resourceNames. - Which
subjects(ServiceAccounts, users, groups) are bound to those roles. - Potential problem indicators:
- Namespaces/workloads that can use PSPs lacking
NET_RAW(orALL) inrequiredDropCapabilities. - Broad bindings (e.g., to
system:authenticatedorsystem:serviceaccounts) to weak PSPs.
- Namespaces/workloads that can use PSPs lacking
# 3) Inspect current pod specs for explicit capability use
# Run on: any machine with kubectl access
# List all pods and their securityContext sections
kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}{" "}{.metadata.name}{"\n"}{.spec.containers[*].securityContext.capabilities}{"\n\n"}{end}'
Review for:
add: ["NET_RAW"]or similar in any container capabilities.- Absence of
drop: ["NET_RAW"]/["ALL"]where your policy expects it. - Potential problem indicators:
- Untrusted or baseline workloads explicitly adding
NET_RAW. - No consistent pattern of dropping
NET_RAWfor non‑privileged workloads.
- Untrusted or baseline workloads explicitly adding
# 4) Focus on high‑risk namespaces (e.g., default, dev, multi‑tenant)
# Run on: any machine with kubectl access
NAMESPACE=default
kubectl get pods -n "$NAMESPACE" -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{.spec.containers[*].securityContext.capabilities}{"\n\n"}{end}'
Again, look for containers adding NET_RAW or not dropping capabilities where required.
# 5) (If PSP is not used) Check Pod Security Admission labels as context
# Run on: any machine with kubectl access
kubectl get ns --show-labels
- While Pod Security Admission does not directly configure
NET_RAW, labels likepod-security.kubernetes.io/enforce=privilegedorbaselineshow how strict each namespace is. - Potential problem indicators:
- Namespaces with
privilegedenforcement used for general or multi‑tenant workloads, where NET_RAW control is more critical.
- Namespaces with
These commands only surface the current state. A human must decide:
- Which workloads legitimately require
NET_RAW. - Which PSPs (or other admission controls) should enforce
requiredDropCapabilities: ["NET_RAW"]or["ALL"]for untrusted workloads.
Automation
#!/usr/bin/env bash
# Report containers that are allowed to keep NET_RAW, by namespace
# Run on: any machine with kubectl access and current-context set to the target cluster
set -euo pipefail
echo "=== 1) Cluster-wide PodSecurityPolicy (if any) and capabilities settings ==="
if kubectl api-resources | awk '{print $1}' | grep -qx PodSecurityPolicy; then
kubectl get psp -o json \
| jq -r '
.items[]
| .metadata.name as $name
| "PSP: \($name)\n allowedCapabilities: \(.spec.allowedCapabilities // [] | join(",") | .? // "-")\n requiredDropCapabilities: \(.spec.requiredDropCapabilities // [] | join(",") | .? // "-")\n"
'
else
echo "PodSecurityPolicy API not present in this cluster."
fi
echo
echo "=== 2) Namespaces and their Pod Security Admission (PSA) labels, if present ==="
kubectl get ns --show-labels
echo
echo "=== 3) Workloads that explicitly ADD NET_RAW capability (cluster-wide) ==="
# This catches pod specs that request NET_RAW in any container
kubectl get pods --all-namespaces -o json \
| jq -r '
.items[]
| .metadata as $m
| .spec as $s
| (
($s.containers // []) + ($s.initContainers // [])
)[]
| select(
(.securityContext.capabilities.add // [])
| index("NET_RAW")
)
| "\($m.namespace)\t\($m.name)\tCONTAINER:\(.name)\tadds NET_RAW"
' | sort || echo "No pods explicitly adding NET_RAW found."
echo
echo "=== 4) Workloads that DO NOT drop NET_RAW or ALL (potentially allowed to keep NET_RAW) ==="
echo "# NOTE: These pods/containers do not declare NET_RAW in 'add',"
echo "# but also do not drop NET_RAW or ALL; admission controls may still restrict them."
echo "# Review by namespace and workload type."
# Helper function implemented inline with jq to print containers missing required drops
kubectl get pods --all-namespaces -o json \
| jq -r '
.items[]
| .metadata as $m
| .spec as $s
| ($s.containers // [] | map(. + {type:"container"})) +
($s.initContainers // [] | map(. + {type:"initContainer"}))
| map(
select(
# Skip if container explicitly drops NET_RAW or ALL
((.securityContext.capabilities.drop // []) | index("NET_RAW") or index("ALL"))
| not
)
)
| select(length > 0)
| [
$m.namespace,
$m.name,
(map("\(.type):\(.name)") | join(",")),
"no drop:NET_RAW/ALL"
]
| @tsv
' | sort || echo "No pods missing drop of NET_RAW/ALL detected."
echo
echo "=== 5) Summary guidance ==="
cat <<'EOF'
Interpretation:
1) PSP / Admission:
- If any PSP has spec.requiredDropCapabilities including NET_RAW or ALL,
and that PSP is bound (via RBAC) to the relevant subjects, those
namespaces are better protected.
- If no PSPs exist, or requiredDropCapabilities does not include NET_RAW/ALL,
admission is not enforcing a drop of NET_RAW.
2) Namespaces:
- Use the namespace labels to correlate with your admission setup
(e.g. Pod Security Admission, OPA/Gatekeeper, Kyverno policies).
3) Explicit NET_RAW use (Section 3):
- Any line here is a definite problem candidate: that container is
explicitly requesting NET_RAW.
- Review why the application needs NET_RAW and move it to a tightly
controlled namespace or remove the capability.
4) Missing required drops (Section 4):
- These pods/containers do not explicitly add NET_RAW, but also do not
drop NET_RAW or ALL in their securityContext.
- If your admission policies do NOT enforce dropping NET_RAW/ALL,
these workloads are at higher risk and should be reviewed:
* Add securityContext.capabilities.drop: ["NET_RAW"] or ["ALL"], and/or
* Enforce requiredDropCapabilities via PSP/PSA/OPA/Kyverno, per your platform.
There is no fully automated fix: a human must decide where NET_RAW is strictly
required, then adjust admission policy and workload manifests accordingly.
EOF