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
Remediation
Manual Steps
-
List all PodSecurityPolicies (PSPs)
- Run on: any machine with kubectl access
kubectl get podsecuritypolicies.policyIf no PSPs are returned, this finding does not apply.
-
Inspect PSPs for
allowedCapabilitiesusage- Run on: any machine with kubectl access
kubectl get podsecuritypolicies.policy -o yaml | grep -nA5 -B5 "allowedCapabilities"Note each PSP name where
allowedCapabilitiesappears and what capabilities are listed. -
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.
- For each PSP that has
-
Tighten or remove
allowedCapabilitiesin 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
allowedCapabilitiesfield entirely from.spec. - If you must keep it, set it to an empty array:
spec:allowedCapabilities: []
- Preferable: remove the
- Apply the updated PSP(s):
kubectl apply -f <psp-name>.yaml
- Export (if needed):
-
Verify no PSPs grant added capabilities
- Run on: any machine with kubectl access
kubectl get podsecuritypolicies.policy -o yaml | grep -n "allowedCapabilities"- Confirm either:
allowedCapabilitiesdoes not appear at all, or- Where it appears, it is set to
allowedCapabilities: [].
-
Monitor for workload impact and adjust if needed
- Watch for pod failures in affected namespaces:
kubectl get pods -Akubectl 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.
- Watch for pod failures in affected namespaces:
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:orallowedCapabilities:- NET_ADMIN- SYS_ADMINallowedCapabilities: ["NET_ADMIN"]allowedCapabilities: null(treated as unrestricted in some versions).
-
A PSP is aligned with this control if:
allowedCapabilitiesfield 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-EMPTYindicates 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.