Skip to main content

Minimize The Admission Containers With Added Capabilities

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 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

Manual Steps
  1. On any machine with kubectl access, list all existing PodSecurityPolicies (if the API is still enabled) and save them for review:

    kubectl get podsecuritypolicies.policy -o wide
    kubectl get podsecuritypolicies.policy -o yaml > /tmp/psps.yaml
  2. Review the saved PSP definitions for allowedCapabilities and any use of NET_RAW (or other added capabilities). Focus on PSPs that are actually referenced by roles/rolebindings:

    # Find all PSPs that declare allowedCapabilities
    yq '.items[] | select(.spec.allowedCapabilities) | {name: .metadata.name, allowedCapabilities: .spec.allowedCapabilities}' /tmp/psps.yaml

    # Explicitly search for NET_RAW
    grep -n "NET_RAW" /tmp/psps.yaml || true

    # Check which PSPs are grantable via RBAC
    kubectl get clusterrole,role -A -o yaml | grep -n "podsecuritypolicies" -n
  3. For each PSP that has spec.allowedCapabilities set (especially including NET_RAW), work with application owners to determine whether those added capabilities are strictly required. Gather the list of workloads using those PSPs (via ServiceAccount → RoleBinding/ClusterRoleBinding → PSP):

    # Example: find bindings that reference a specific PSP
    kubectl get clusterrole,role -A -o yaml | grep -n "name: <PSP-NAME>"
    kubectl get clusterrolebinding,rolebinding -A -o yaml | grep -n "<ROLE-NAME>"
    # Then map each bound ServiceAccount to its workloads
    kubectl get pods -A -o wide --field-selector spec.serviceAccountName=<SA-NAME>
  4. Where possible, modify the PSP manifests (YAML files in your Git/IaC or export/edit in-place) to remove allowedCapabilities entirely or set it to an empty list, ensuring that NET_RAW (and other added capabilities) are not permitted by default:

    # Example edit for a PSP manifest (run in your IaC/Git repo, then apply)
    # Before:
    # spec:
    # allowedCapabilities:
    # - NET_RAW
    # After:
    # spec:
    # allowedCapabilities: []
    #
    # Apply the corrected PSP
    kubectl apply -f corrected-psp.yaml
  5. If a workload truly needs NET_RAW or other capabilities, document the justification, scope the PSP (or successor policy mechanism) as narrowly as possible (specific namespaces/service accounts), and ensure no broad “catch-all” PSPs grant allowedCapabilities cluster-wide. Update corresponding RBAC to limit who can use those PSPs:

    # Example: inspect and then edit a binding to ensure only the intended SA/namespace can use the PSP
    kubectl get clusterrolebinding <BINDING-NAME> -o yaml > /tmp/binding.yaml
    # Edit /tmp/binding.yaml to narrow subjects, then:
    kubectl apply -f /tmp/binding.yaml
  6. Verify the state after changes: confirm no PSPs grant added capabilities except where explicitly and narrowly justified, and that NET_RAW is not permitted by default:

    kubectl get podsecuritypolicies.policy -o yaml > /tmp/psps-post.yaml

    yq '.items[] | select(.spec.allowedCapabilities) | {name: .metadata.name, allowedCapabilities: .spec.allowedCapabilities}' /tmp/psps-post.yaml

    grep -n "NET_RAW" /tmp/psps-post.yaml || echo "No PSPs explicitly allow NET_RAW"
Using kubectl

Using kubectl

Run these commands from any machine with kubectl access.

  1. List all PodSecurityPolicies and see allowedCapabilities

    kubectl get podsecuritypolicies.policy \
    -o=jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.allowedCapabilities}{"\n"}{end}'

    Indicates a problem: Any PSP where the second column is not [] or <nil> (i.e., shows capabilities such as ["NET_RAW"], ["NET_ADMIN" "NET_RAW"], or ["*"]).

  2. View full details for PSPs that have allowedCapabilities set
    Replace psp-name with each PSP name from step 1 that showed non-empty capabilities.

    kubectl get podsecuritypolicy psp-name -o yaml

    What to look for:

    • Under .spec.allowedCapabilities, check for NET_RAW or wildcard '*', or other added Linux capabilities.
    • Example problematic snippet:
      spec:
      allowedCapabilities:
      - NET_RAW
      - NET_ADMIN
  3. Discover which namespaces might be using PSPs with extra capabilities

    a. Check RBAC bindings that reference PSPs:

    kubectl get role,clusterrole,rolebinding,clusterrolebinding -A \
    -o yaml | grep -A5 -n "podsecuritypolicies" | sed -n '1,160p'

    Indicates a problem: References to PSPs you identified as having non-empty allowedCapabilities, especially if they are bound cluster‑wide or to broad subjects like system:serviceaccounts, system:authenticated, or system:serviceaccounts:<namespace>.

    b. For each such binding, inspect it in detail, for example:

    kubectl get clusterrolebinding binding-name -o yaml
    kubectl get rolebinding -n namespace-name binding-name -o yaml

    What to look for:

    • roleRef pointing to a PSP-granting ClusterRole.
    • subjects that are wide in scope (many users/service accounts), meaning many pods can get extra capabilities like NET_RAW.
  4. (If PSPs are not used but PSP objects still exist) Confirm whether any pods are actually using added capabilities via SecurityContext (to understand current risk)

    kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{.spec.containers[*].securityContext.capabilities}{"\n"}{end}' \
    | grep -v "{}" || true

    Indicates a problem: Lines where capabilities include NET_RAW or add: ["NET_RAW"]. This does not prove a PSP issue directly, but it shows where elevated capabilities are being used and where PSPs (or other policies) should be tightened.

These commands only expose the current configuration and usage. Deciding whether and how to remove or restrict allowedCapabilities (especially NET_RAW) requires human review of application needs and potential operational impact.

Automation
#!/usr/bin/env bash
# Report PodSecurityPolicies / Pod Security admission config that allow NET_RAW

set -euo pipefail

echo "=== Context ==="
kubectl config current-context
echo

########################################
# 1) Legacy PodSecurityPolicy (PSP)
########################################

echo "=== PodSecurityPolicies that allow added capabilities (non-empty allowedCapabilities) ==="
kubectl get psp -o json 2>/dev/null | jq '
.items[]
| select(.spec.allowedCapabilities != null and (.spec.allowedCapabilities | length > 0))
| {
name: .metadata.name,
allowedCapabilities: .spec.allowedCapabilities
}
' || echo "No PSP API found (likely PSP is not enabled on this cluster)."
echo

echo "=== PodSecurityPolicies that explicitly allow NET_RAW via allowedCapabilities or defaultAddCapabilities ==="
kubectl get psp -o json 2>/dev/null | jq '
.items[]
| select(
(.spec.allowedCapabilities // [] | map(. == "NET_RAW") | any)
or
(.spec.defaultAddCapabilities // [] | map(. == "NET_RAW") | any)
)
| {
name: .metadata.name,
allowedCapabilities: .spec.allowedCapabilities,
defaultAddCapabilities: .spec.defaultAddCapabilities
}
' || true
echo

echo "NOTE:"
echo "- Any PSP listed above with a non-empty .spec.allowedCapabilities violates the benchmark guidance"
echo " (allowedCapabilities should be absent or an empty array)."
echo "- Any PSP listing NET_RAW in allowedCapabilities or defaultAddCapabilities is a high‑risk configuration."
echo

########################################
# 2) Pod Security admission (if PSP is not used)
########################################

echo "=== Namespaces with Pod Security labels (pod-security.kubernetes.io/*) ==="
kubectl get ns --show-labels | sed '1p;/pod-security.kubernetes.io/d' || true
echo
echo "Review namespaces that are not at least 'restricted' level for potential over‑permissive pod capabilities."
echo

########################################
# 3) Workloads actually requesting NET_RAW
########################################

echo "=== Pods whose containers request NET_RAW capability (current state) ==="
kubectl get pods --all-namespaces -o json | jq -r '
.items[]
| . as $pod
| (
($pod.spec.initContainers // [])
+ ($pod.spec.containers // [])
)[]
| select(
(.securityContext.capabilities.add // [])
| map(. == "NET_RAW")
| any
)
| [
$pod.metadata.namespace,
$pod.metadata.name,
.name,
( .securityContext.capabilities.add // [] | join(",") )
]
| @tsv
' | awk 'BEGIN{OFS="\t"; print "NAMESPACE","POD","CONTAINER","ADDED_CAPABILITIES"}1' || true
echo

echo "=== Deployments / StatefulSets / DaemonSets specifying NET_RAW in pod templates ==="
for kind in deployment statefulset daemonset; do
echo "--- $kind ---"
kubectl get "$kind" --all-namespaces -o json 2>/dev/null | jq -r "
.items[]
| . as \$w
| (
(\$w.spec.template.spec.initContainers // [])
+ (\$w.spec.template.spec.containers // [])
)[]
| select(
(.securityContext.capabilities.add // [])
| map(. == \"NET_RAW\")
| any
)
| [
\$w.kind,
\$w.metadata.namespace,
\$w.metadata.name,
.name,
(.securityContext.capabilities.add // [] | join(\",\"))
]
| @tsv
" | awk 'BEGIN{OFS="\t"; print "KIND","NAMESPACE","WORKLOAD","CONTAINER","ADDED_CAPABILITIES"}1' || true
echo
done

cat <<'EOF'

INTERPRETING THE OUTPUT:

1) PodSecurityPolicies:
- PROBLEM if any PSP appears under:
"PodSecurityPolicies that allow added capabilities (non-empty allowedCapabilities)"
because the benchmark requires allowedCapabilities to be absent or an empty array.
- HIGH-RISK if any PSP lists NET_RAW in allowedCapabilities or defaultAddCapabilities.

2) Namespaces:
- Namespaces without strong Pod Security labels (e.g., not at 'restricted' level)
should be reviewed; they are more likely to admit pods with extra capabilities.

3) Workloads / Pods:
- Any entry in the NET_RAW sections (pods or workloads) indicates a pod template
that is explicitly adding NET_RAW. Each must be reviewed to decide if NET_RAW
is strictly necessary, and, if not, removed from the manifest.

No automated change is made by this script; it is intended for review and risk assessment.
EOF

Additional Reading: