Skip to main content

Minimize The Admission Of Containers With Added Capabilities

More Info:

Do not generally permit containers with capabilities assigned beyond the default set.

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. List all PodSecurityPolicies (PSPs)

    • Run on: any machine with kubectl access
    kubectl get podsecuritypolicies.policy

    If no PSPs are returned, this finding does not apply.

  2. Inspect PSPs for allowedCapabilities usage

    • Run on: any machine with kubectl access
    kubectl get podsecuritypolicies.policy -o yaml | grep -nA5 -B5 "allowedCapabilities"

    Note each PSP name where allowedCapabilities appears and what capabilities are listed.

  3. Decide which workloads actually require extra capabilities

    • For each PSP that has allowedCapabilities, identify the namespaces/service accounts using it:
      kubectl get role,rolebinding,clusterrole,clusterrolebinding -A -o wide \
      | grep -E "podsecuritypolicies|podsecuritypolicy"
    • Review the deployments/daemonsets/statefulsets in those namespaces to determine which applications truly need specific Linux capabilities and why (e.g., low‑level networking, privileged storage drivers). Document required capabilities per workload.
  4. Tighten or remove allowedCapabilities in PSP manifests

    • For PSPs where no workloads strictly need extra capabilities, plan to remove the field or set it to an empty list.
    • For PSPs where extra capabilities are justified, restrict them to the minimal, documented set required.
    • Edit the PSP manifest(s) (from your Git/IaC or by exporting, editing, and re‑applying):
      • Export (if needed):
        kubectl get podsecuritypolicy.policy <psp-name> -o yaml > <psp-name>.yaml
      • In each <psp-name>.yaml:
        • Preferable: remove the allowedCapabilities field entirely from .spec.
        • If you must keep it, set it to an empty array:
          spec:
          allowedCapabilities: []
      • Apply the updated PSP(s):
        kubectl apply -f <psp-name>.yaml
  5. Verify no PSPs grant added capabilities

    • Run on: any machine with kubectl access
    kubectl get podsecuritypolicies.policy -o yaml | grep -n "allowedCapabilities"
    • Confirm either:
      • allowedCapabilities does not appear at all, or
      • Where it appears, it is set to allowedCapabilities: [].
  6. Monitor for workload impact and adjust if needed

    • Watch for pod failures in affected namespaces:
      kubectl get pods -A
      kubectl describe pod -n <namespace> <pod-name>
    • If pods fail due to missing capabilities, reassess and reintroduce only the specific, minimally required capabilities into the relevant PSP, then re‑verify using step 5.
Using kubectl
# 1) List all PodSecurityPolicies
# Run on: any machine with kubectl access
kubectl get podsecuritypolicies.policy

# 2) Inspect all PSPs and surface capabilities configuration
kubectl get podsecuritypolicies.policy -o yaml | sed -n '/^---/p;/^metadata:/,/^---/p' | grep -E '^(metadata:| name:| *allowedCapabilities:| *requiredDropCapabilities:| *defaultAddCapabilities:| *allowedCapabilities: \[\])'

# 3) For detailed review of a specific PSP (replace <psp-name>)
kubectl get podsecuritypolicies.policy <psp-name> -o yaml

Review guidance:

  • A PSP is problematic for this control if its YAML contains either:

    • allowedCapabilities: with one or more items, for example:
      allowedCapabilities:
      - NET_ADMIN
      - SYS_ADMIN
      or
      allowedCapabilities: ["NET_ADMIN"]
    • allowedCapabilities: null (treated as unrestricted in some versions).
  • A PSP is aligned with this control if:

    • allowedCapabilities field is absent entirely, or
    • Present but set to an empty array, for example:
      allowedCapabilities: []

Use the per‑PSP kubectl get ... -o yaml output to decide, with application owners, whether any non-empty allowedCapabilities are strictly required before planning changes in manifests or admission policy.

Automation
#!/usr/bin/env bash
# Report PodSecurityPolicies that allow added capabilities (CIS GKE 4.2.8)
# Run on: any machine with kubectl access and current context set to the target cluster

set -euo pipefail

echo "Checking for PodSecurityPolicies with non-empty allowedCapabilities ..."

# 1) Summary: which PSPs define allowedCapabilities and whether they are empty
echo
echo "=== Summary of allowedCapabilities per PodSecurityPolicy ==="
kubectl get psp -o json \
| jq -r '
.items[]
| {
name: .metadata.name,
allowedCapabilities: (
.spec.allowedCapabilities
// []
)
}
| [
.name,
(if (.allowedCapabilities | length) == 0 then "EMPTY" else "NON-EMPTY" end),
(.allowedCapabilities | join(","))
]
| @tsv
' \
| column -t -s$'\t'

# 2) Detailed listing of PSPs that violate the recommendation
echo
echo "=== PSPs with NON-EMPTY allowedCapabilities (REVIEW REQUIRED) ==="
kubectl get psp -o json \
| jq -r '
.items[]
| select((.spec.allowedCapabilities // []) | length > 0)
| [
.metadata.name,
(.spec.allowedCapabilities | join(",")),
(.metadata.annotations."kubernetes.io/description" // "")
]
| @tsv
' \
| column -t -s$'\t' || echo "None found."

# 3) Show which service accounts / pods are using those PSPs (where possible)
# This relies on the psp admission plugin behavior / annotations in many clusters.
echo
echo "=== Pods bound to PSPs with NON-EMPTY allowedCapabilities (best-effort) ==="
PROBLEM_PSPS=$(kubectl get psp -o json \
| jq -r '.items[]
| select((.spec.allowedCapabilities // []) | length > 0)
| .metadata.name')

if [ -z "$PROBLEM_PSPS" ]; then
echo "No PSPs with non-empty allowedCapabilities detected."
exit 0
fi

for psp in $PROBLEM_PSPS; do
echo
echo "PSP: $psp"
# Look for pods that advertise the PSP they were admitted under
kubectl get pods --all-namespaces -o json \
| jq -r --arg psp "$psp" '
.items[]
| select(
.metadata.annotations."kubernetes.io/psp" == $psp
or .metadata.annotations."eks.amazonaws.com/psp" == $psp
or .metadata.annotations."psp" == $psp
)
| [
.metadata.namespace,
.metadata.name,
(.spec.serviceAccountName // "default")
]
| @tsv
' \
| awk 'BEGIN { OFS="\t"; print "NAMESPACE","POD","SERVICEACCOUNT" } { print }' \
|| echo " No pods found with explicit PSP annotation = $psp"
done

echo
echo "=== Interpretation ==="
echo "- Any PSP shown as NON-EMPTY in the summary is a potential policy problem."
echo "- PSPs listed under 'PSPs with NON-EMPTY allowedCapabilities' violate the CIS recommendation"
echo " unless there is a documented, justified exception."
echo "- Pods listed under each PSP show which workloads are currently relying on that PSP."

Explanation of problematic output:

  • In the “Summary of allowedCapabilities per PodSecurityPolicy” section, any row where the second column is NON-EMPTY indicates a PSP that does not comply with the recommendation.
  • In the “PSPs with NON-EMPTY allowedCapabilities (REVIEW REQUIRED)” section, every listed PSP must be manually reviewed; these are the specific PSPs that allow extra capabilities.
  • For each such PSP, any pods shown under “Pods bound to PSPs with NON-EMPTY allowedCapabilities” are the workloads currently depending on that relaxed policy and should be part of the manual risk/exception review.

Additional Reading: