Skip to main content

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​

Manual Steps
  1. On any machine with kubectl access, list all namespaces and current pod security configuration to understand what’s enforcing capabilities today:

    kubectl get ns
    kubectl get psp
    kubectl get psp -o yaml
    kubectl get podsecuritypolicies.policy -o yaml
    kubectl get ns --show-labels

    If 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).

  2. 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 ALL
    kubectl 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") | not
    and (.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"
  3. 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_RAW
    kubectl 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 ALL
    kubectl 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.

  4. Decide on a policy approach per namespace:

    • If PSP is available: design one or more PSPs that set:
      spec:
      requiredDropCapabilities:
      - NET_RAW
      or:
      spec:
      requiredDropCapabilities:
      - ALL
      Then update RBAC so that only tightly‑controlled subjects can use any PSPs that allow NET_RAW (if such PSPs are truly necessary).
    • If PSP is not available: implement equivalent restrictions via your cluster’s policy mechanism (e.g., Pod Security Admission with restricted profile and custom policies, or OPA/Gatekeeper/Kyverno) and ensure they reject pods that add NET_RAW and/or do not drop it.
  5. 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
  6. Verify the effective state matches your intent:

    # Confirm PSP or equivalent policy contains requiredDropCapabilities NET_RAW or ALL
    kubectl get psp -o yaml | grep -A3 "requiredDropCapabilities"

    # Confirm no unexpected pods can run with NET_RAW
    kubectl 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:
    • requiredDropCapabilities is missing or empty.
    • requiredDropCapabilities does not contain NET_RAW or ALL.
    • 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 (or ALL) in requiredDropCapabilities.
    • Broad bindings (e.g., to system:authenticated or system:serviceaccounts) to weak PSPs.

# 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_RAW for non‑privileged workloads.

# 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 like pod-security.kubernetes.io/enforce=privileged or baseline show how strict each namespace is.
  • Potential problem indicators:
    • Namespaces with privileged enforcement used for general or multi‑tenant workloads, where NET_RAW control is more critical.

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

Additional Reading:​