Minimize The Admission Containers With Net_Raw Capability
More Info:
Do not generally permit containers to be run as the root user.
Risk Level
Critical
Address
Security
Compliance Standards
- APRA CPS 234 (Australia)
- BSI C5 (Germany)
- Brazil LGPD
- CCPA / CPRA (California)
- CIS AKS
- CIS Critical Security Controls v8
- 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
-
From any machine with kubectl access, list all namespaces and identify which ones are allowed to run user workloads (exclude system namespaces such as kube-system, kube-public, kube-node-lease, gatekeeper-system, etc.):
kubectl get ns -
For each non-system namespace, review what Pod Security controls are in place (PSPs if still in use, or Pod Security Admission labels / Gatekeeper / Kyverno, etc.). Start by checking Pod Security Admission labels:
kubectl get ns --show-labelsLook for
pod-security.kubernetes.io/*labels. Namespaces lacking these labels or usingprivilegedlevels are higher risk and should be prioritized. -
In each high‑risk namespace, identify pods (and pod‑templates) that are currently using or could use extra capabilities by inspecting their securityContext:
kubectl get pods -n <NAMESPACE> -o json | jq '.items[].spec.containers[]?.securityContext // {}'Also inspect common controllers:
kubectl get deploy,sts,ds,job,cronjob -n <NAMESPACE> -o yaml | grep -nE 'securityContext|capabilities' -C2Manually review results for
capabilities:,add:, especially any mention ofNET_RAW. -
If PodSecurityPolicy (PSP) is still enabled in the cluster, list and inspect PSPs to see whether they require dropping
NET_RAW:kubectl get pspkubectl get psp -o yaml | grep -nE 'requiredDropCapabilities|NET_RAW|ALL' -C3Determine whether all namespaces where workloads run are bound (via RBAC) to PSPs that have
.spec.requiredDropCapabilitiesincludingNET_RAWorALL. If not, note which namespaces and service accounts are effectively exempt. -
Based on the review, decide on changes:
- For PSP-based clusters: design or update PSPs to include
NET_RAW(orALL) in.spec.requiredDropCapabilitiesand ensure appropriate RBAC bindings so all workload service accounts in your target namespaces are constrained by these PSPs. - For clusters without PSP: update or create equivalent admission controls (e.g., Gatekeeper/Kyverno policies, or rely on Pod Security Admission “restricted” profile) that enforce dropping
NET_RAW, and update deployment manifests so containers do not explicitly addNET_RAW.
- For PSP-based clusters: design or update PSPs to include
-
After policy and manifest changes, re-check selected namespaces to confirm no pods can (or do) add
NET_RAW:kubectl get deploy,sts,ds,job,cronjob -n <NAMESPACE> -o yaml | grep -nE 'capabilities' -C3If PSP is used, ensure all enforced PSPs now show
requiredDropCapabilitiesincludingNET_RAWorALL:kubectl get psp -o yaml | grep -nE 'requiredDropCapabilities' -C3
Using kubectl
# 1) List all namespaces and any PodSecurity standard labels
# Run on: any machine with kubectl access
kubectl get ns --show-labels
Problem indication:
- Namespaces without any
pod-security.kubernetes.io/*labels, or - Namespaces labeled
pod-security.kubernetes.io/enforce=privileged(or unset but with privileged behavior configured elsewhere) suggest weaker controls, so NET_RAW is more likely to be allowed.
# 2) Inspect PodSecurity admission settings (if labels suggest problems)
# Replace <namespace> with a namespace of interest
kubectl describe ns <namespace>
Problem indication:
Labels:section missingpod-security.kubernetes.io/enforceor set toprivileged.- No other admission mechanism (e.g., Gatekeeper, Kyverno) visible in annotations that would restrict capabilities.
# 3) Identify pods that explicitly add NET_RAW capability
# Run cluster-wide search
kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{.spec.containers[*].securityContext.capabilities.add}{"\n"}{end}' \
| grep -i NET_RAW || echo "No pods explicitly adding NET_RAW found"
Problem indication:
- Any line where the third column includes
NET_RAWshows a pod that is explicitly requesting this capability. - Focus especially on non-system namespaces where such capability is generally unnecessary.
# 4) Check for privileged or overly-permissive pods
kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{.spec.containers[*].securityContext.privileged}{"\n"}{end}' \
| grep -E "true$" || echo "No privileged pods reported"
Problem indication:
- Any
truevalue indicates a privileged container; privileged containers effectively bypass capability restrictions, so NET_RAW may be available even if not explicitly added.
# 5) Review workload manifests for capability configuration in a target namespace
# Replace <namespace> appropriately
kubectl get pod -n <namespace> -o yaml > /tmp/pods-<namespace>.yaml
Manually review the dumped YAML:
- Look under
spec.containers[].securityContext.capabilities.addforNET_RAW. - Check that
spec.containers[].securityContext.capabilities.dropincludesALLor at leastNET_RAW.
Problem indication:
- Containers with
capabilities.addincludingNET_RAW. - Containers missing a
droplist, or withdropnot includingALLorNET_RAW, in namespaces where this capability should not be allowed.
# 6) Verify whether legacy PodSecurityPolicies (if still enabled) restrict NET_RAW
kubectl get psp
If PSPs exist:
kubectl get psp -o yaml > /tmp/psp-all.yaml
Manually review:
- Ensure
.spec.requiredDropCapabilitiesincludesNET_RAWorALL. - Check any PSPs bound via Roles/ClusterRoles to the at‑risk namespaces.
Problem indication:
- PSPs used by application namespaces where
.spec.requiredDropCapabilitiesis empty, or - PSPs that do not include
NET_RAWorALLinrequiredDropCapabilities, and are the ones applied to those namespaces.
Automation
#!/usr/bin/env bash
# Purpose: Report containers that can potentially use NET_RAW across the cluster
# Run on: any machine with kubectl access and current context set
set -euo pipefail
echo "=== 1) Cluster-wide PodSecurityPolicy (PSP) / PodSecurity admission overview ==="
# PSP is deprecated but still used in some clusters; also show PodSecurity labels.
echo
echo "--- PodSecurityPolicies (if any) ---"
kubectl get psp -o wide 2>/dev/null || echo "No PodSecurityPolicies found or PSP not supported"
echo
echo "--- Namespaces with Pod Security admission labels ---"
kubectl get ns -o json \
| jq -r '.items[] | {name: .metadata.name, labels: .metadata.labels} |
[.name,
( .labels["pod-security.kubernetes.io/enforce"] // "-" ),
( .labels["pod-security.kubernetes.io/enforce-version"] // "-" ),
( .labels["pod-security.kubernetes.io/audit"] // "-" ),
( .labels["pod-security.kubernetes.io/warn"] // "-" )
] | @tsv' 2>/dev/null \
| awk 'BEGIN{printf "%-30s %-10s %-10s %-10s %-10s\n","NAMESPACE","ENFORCE","ENF_VER","AUDIT","WARN"}
{printf "%-30s %-10s %-10s %-10s %-10s\n",$1,$2,$3,$4,$5}' \
|| echo "No Pod Security admission labels detected (or jq not installed)."
echo
echo "=== 2) Current pods with NET_RAW explicitly added via securityContext.capabilities ==="
echo "NOTE: This looks for NET_RAW in container securityContext; it does NOT detect"
echo " default capabilities inherited from the container runtime."
kubectl get pods --all-namespaces -o json \
| jq -r '
.items[]
| . as $pod
| ($pod.spec.containers + ($pod.spec.initContainers // []))[]
| . as $c
| {
ns: $pod.metadata.namespace,
pod: $pod.metadata.name,
container: .name,
adds: (.securityContext.capabilities.add // []),
drops: (.securityContext.capabilities.drop // [])
}
| select(.adds | index("NET_RAW"))
| "\(.ns)\t\(.pod)\t\(.container)\tadds:\(.adds|join(","))\tdrops:\(.drops|join(","))"
' 2>/dev/null \
| awk 'BEGIN{printf "%-30s %-40s %-25s %-30s %-30s\n","NAMESPACE","POD","CONTAINER","ADDS","DROPS"}
{printf "%-30s %-40s %-25s %-30s %-30s\n",$1,$2,$3,$4,$5}' \
|| echo "No pods with NET_RAW explicitly added found (or jq not installed)."
echo
echo "=== 3) Workload specs that add NET_RAW in Pod templates (Deployments, DaemonSets, etc.) ==="
echo "This finds controllers whose pod templates add NET_RAW; new pods from them will do the same."
# Helper function for controllers with pod templates
report_controller() {
local kind="$1"
echo
echo "--- ${kind}s with NET_RAW added ---"
kubectl get "${kind,,}" --all-namespaces -o json 2>/dev/null \
| jq -r --arg KIND "$kind" '
.items[]
| . as $obj
| ($obj.spec.template.spec.containers + ($obj.spec.template.spec.initContainers // []))[]
| . as $c
| {
kind: $KIND,
ns: $obj.metadata.namespace,
name: $obj.metadata.name,
container: .name,
adds: (.securityContext.capabilities.add // []),
drops: (.securityContext.capabilities.drop // [])
}
| select(.adds | index("NET_RAW"))
| "\(.kind)\t\(.ns)\t\(.name)\t\(.container)\tadds:\(.adds|join(","))\tdrops:\(.drops|join(","))"
' 2>/dev/null \
| awk -v K="$kind" 'BEGIN{printf "%-12s %-30s %-40s %-25s %-30s %-30s\n","KIND","NAMESPACE","NAME","CONTAINER","ADDS","DROPS"}
{printf "%-12s %-30s %-40s %-25s %-30s %-30s\n",$1,$2,$3,$4,$5,$6}' \
|| echo "No ${kind}s explicitly adding NET_RAW (or jq not installed)."
}
report_controller "Deployment"
report_controller "DaemonSet"
report_controller "StatefulSet"
report_controller "ReplicaSet"
report_controller "Job"
report_controller "CronJob"
echo
echo "=== 4) Namespaces where NET_RAW is NOT required to be dropped by PSP (if PSP present) ==="
echo "This section is only relevant if PodSecurityPolicy is enabled."
# List PSPs and whether they require dropping NET_RAW or ALL
kubectl get psp -o json 2>/dev/null \
| jq -r '
.items[]
| {
name: .metadata.name,
requiredDrops: (.spec.requiredDropCapabilities // [])
}
| "\(.name)\trequiredDrop:\(.requiredDrops|join(","))"
' 2>/dev/null \
| awk 'BEGIN{printf "%-40s %-40s\n","PSP","REQUIRED_DROP_CAPABILITIES"}
{printf "%-40s %-40s\n",$1,$2}' \
|| echo "No PSP data available; PSP may not be enabled or jq missing."
echo
echo "=== INTERPRETING RESULTS ==="
cat <<'EOF'
Potential problems that require review:
1) Pods / controllers explicitly adding NET_RAW:
- Any row in sections (2) or (3) indicates a container that *requests* NET_RAW.
- Review whether NET_RAW is strictly required for that workload.
- If not required, remove NET_RAW from securityContext.capabilities.add.
- Prefer dropping NET_RAW (or ALL) at policy level (PSP or Pod Security / admission) where possible.
2) Weak or missing cluster-wide policy:
- If no PSPs are present AND Pod Security admission labels are absent or set to a level
that allows NET_RAW (e.g., custom or "privileged"), then nothing is centrally preventing
workloads from using NET_RAW.
- Namespaces without Pod Security labels, or with very permissive settings, should be
reviewed and strengthened as appropriate for your environment.
This script does NOT:
- Detect implicit default capabilities granted by the container runtime.
- Enforce any policy automatically.
Use these reports to decide where to:
- Tighten policies (e.g., require dropping NET_RAW or ALL).
- Refactor workloads that currently rely on NET_RAW.
EOF