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: