Minimize Admission Of Containers Capabilities Assigned
More Info:
Do not generally permit containers with capabilities
Risk Level
Low
Address
Security
Compliance Standards
- CIS Kubernetes
Triage and Remediation
- Remediation
Remediation
Manual Steps
-
Identify namespaces where dropping all capabilities is acceptable
- On any machine with kubectl access:
kubectl get ns
- With your app/service owners, list namespaces whose workloads are non-privileged, non-infrastructure and can reasonably run without extra Linux capabilities (for example, pure HTTP APIs, batch jobs, or frontends).
- On any machine with kubectl access:
-
Inventory current capability usage in those namespaces
- For each candidate namespace (replace
TARGET_NS):kubectl get pods -n TARGET_NS -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{range .spec.containers[*]} {.name}{" caps:"}{.securityContext.capabilities}{"\n"}{end}{"\n"}{end}' - Also capture full security contexts for deeper review:
kubectl get pods -n TARGET_NS -o yaml > TARGET_NS-pods.yaml
- Review for any
capAddentries and for containers that do not specifydrop: ["ALL"].
- For each candidate namespace (replace
-
Decide which workloads actually need capabilities
- For each container with
capAdd(or nodrop: ["ALL"]), validate with the application owner and documentation whether these capabilities are functionally required. - Mark containers that:
- Do not need any capabilities → should drop all.
- Need only specific capabilities → should drop all by default and add back only the minimal required ones.
- Where uncertain, plan controlled tests with reduced capabilities in a non‑production environment.
- For each container with
-
Enforce “drop all capabilities” at the namespace level via policy
- If you already use a policy engine (Pod Security Standards / Pod Security Admission, Kyverno, OPA Gatekeeper, or a PSP-like replacement), define or adjust a policy for each selected namespace to require
drop: ["ALL"]and optionally forbidcapAddexcept for explicitly allowed cases. For example, using Kyverno (on any machine with kubectl access):kubectl apply -f - << 'EOF'apiVersion: kyverno.io/v1kind: ClusterPolicymetadata:name: require-drop-all-capabilitiesspec:validationFailureAction: enforcerules:- name: require-drop-allmatch:any:- resources:kinds: ["Pod"]namespaces: ["TARGET_NS"]validate:message: "Containers must drop all Linux capabilities."pattern:spec:containers:- securityContext:capabilities:drop:- "ALL"# Optionally add a rule to block capAdd, except where explicitly allowedEOF - Adjust the example to your policy engine and list of target namespaces; review carefully before enforcing in production.
- If you already use a policy engine (Pod Security Standards / Pod Security Admission, Kyverno, OPA Gatekeeper, or a PSP-like replacement), define or adjust a policy for each selected namespace to require
-
Update existing workloads that violate the policy
- For each deployment/statefulset/daemonset in the target namespaces, edit the manifest to drop all capabilities (example for a deployment):
Editkubectl -n TARGET_NS get deploy APP_NAME -o yaml > APP_NAME-deploy.yaml
APP_NAME-deploy.yamlto include, under each container:Then apply:securityContext:capabilities:drop:- "ALL"kubectl apply -f APP_NAME-deploy.yaml - For pods created by other controllers (CronJobs, Jobs, Operators), update the relevant higher-level resource templates similarly.
- For each deployment/statefulset/daemonset in the target namespaces, edit the manifest to drop all capabilities (example for a deployment):
-
Verify effective enforcement and absence of unintended capabilities
- Attempt to create a pod without dropping all capabilities in the protected namespace; confirm admission is rejected according to your policy engine.
- Confirm running pods comply:
kubectl get pods -n TARGET_NS -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{range .spec.containers[*]} {.name}{" caps:"}{.securityContext.capabilities}{"\n"}{end}{"\n"}{end}'
- Periodically re-run this review when new workloads are added or when application requirements change.
Using kubectl
# 1) List all namespaces
# Run on: any machine with kubectl access
kubectl get ns -o wide
Review this list and pick a namespace you expect should not need elevated capabilities (for example, “frontend”, “dev”, “testing”, or other app-only namespaces).
# 2) Find pods in a namespace that define container capabilities
# Replace <NAMESPACE> with the namespace under review
kubectl get pods -n <NAMESPACE> -o jsonpath='
{range .items[*]}
POD: {@.metadata.name}{"\n"}
{range @.spec.containers[*]}
CONTAINER: {@.name}{"\n"}
add: {@.securityContext.capabilities.add}{"\n"}
drop: {@.securityContext.capabilities.drop}{"\n"}
{end}{"\n"}
{end}'
Problem indication:
- Any non-empty
add:line (for example[NET_ADMIN CAP_SYS_ADMIN]) means the container is requesting extra capabilities. - Missing or empty
drop:where you expect all capabilities to be dropped may be a concern if the app does not need capabilities.
# 3) Show full securityContext for all containers in a namespace
kubectl get pods -n <NAMESPACE> -o jsonpath='
{range .items[*]}
POD: {@.metadata.name}{"\n"}
{range @.spec.containers[*]}
CONTAINER: {@.name}{"\n"}
securityContext: {@.securityContext}{"\n"}
{end}{"\n"}
{end}'
Problem indication:
securityContext.capabilities.addpresent with any capability values.- No
securityContext.capabilities.dropand no higher-level policy (see below) in a namespace that should be locked down.
# 4) Inspect PodSecurityPolicy (if in use; deprecated on some platforms)
kubectl get psp
kubectl get psp -o yaml
Problem indication:
allowedCapabilitiescontains capabilities beyond what is needed, especially*.requiredDropCapabilitiesis empty or does not includeALLfor namespaces that should drop all capabilities.
# 5) Inspect Pod Security Admission (Pod Security Standards) labels on namespaces (if used)
kubectl get ns --show-labels
Look for labels like pod-security.kubernetes.io/enforce=privileged|baseline|restricted.
Problem indication:
- Namespaces that should run unprivileged workloads but are labeled with
privilegedor have no Pod Security labels and permit capabilities via other policies.
# 6) Inspect admission policies that might control capabilities (PSA/PSP replacements)
# Example for Kyverno:
kubectl get clusterpolicy,policy -A -o yaml
# Example for OPA Gatekeeper:
kubectl get constrainttemplate,constraint -A -o yaml
Problem indication:
- No policy that restricts
securityContext.capabilitiesfor namespaces that do not need capabilities. - Policies explicitly allowing broad or unrestricted capabilities.
# 7) Spot-check specific pods that look suspicious
# Replace <POD> and <NAMESPACE>
kubectl get pod <POD> -n <NAMESPACE> -o yaml
Problem indication:
securityContext.capabilities.addwith capabilities likeNET_ADMIN,SYS_ADMIN,NET_RAW, or many entries.- Containers running as root plus added capabilities without a clear business need.
Use the above outputs to decide, per namespace, whether workloads truly require capabilities; if not, plan to introduce or tighten policies that require dropping all capabilities and/or forbid adding new ones.
Automation
#!/usr/bin/env bash
# Report pods and workloads that grant Linux capabilities (add or fail to drop all)
# Run on: any machine with kubectl access to the cluster
set -euo pipefail
echo "=== Cluster-wide capabilities usage report ==="
echo "Timestamp: $(date -Iseconds)"
echo
# 1) Show any Pod security policies / PSS exemptions that might allow capabilities (if PSP still exists)
echo "== PodSecurityPolicies (if present) =="
kubectl get psp -o yaml 2>/dev/null | grep -nE 'allowedCapabilities|defaultAddCapabilities|requiredDropCapabilities' || \
echo "No PSPs found or PSP not enabled."
echo
# 2) List all pods with any explicit capabilities in their containers or initContainers
echo "== Pods with capabilities configured (add/drop) =="
kubectl get pods --all-namespaces -o json \
| jq -r '
.items[]
| {
ns: .metadata.namespace,
pod: .metadata.name,
containers: (
([.spec.containers[], (.spec.initContainers // [])[]]
| {
name: .name,
add: (.securityContext.capabilities.add // [] | map(.)),
drop: (.securityContext.capabilities.drop // [] | map(.))
})
)
}
| select(
([.containers[]?.add[]?] | length) > 0
or
(
# flag containers that do NOT drop ALL capabilities
([.containers[]?.drop[]?] | length) == 0
or
( [.containers[]?.drop[]? | ascii_upcase] | index("ALL") | not )
)
)
| "NAMESPACE=\(.ns) POD=\(.pod)\n"
+ (
[.containers[]
| " container=\(.name)\n"
+ " add: \(.add | if length==0 then \"[]\" else join(\",\") end)\n"
+ " drop: \(.drop | if length==0 then \"[]\" else join(\",\") end)"
] | join("\n")
)
' 2>/dev/null || echo "Failed to query pods or jq not installed."
echo
# 3) Summarize by namespace: any pod that does NOT drop ALL capabilities
echo "== Namespaces with pods that do NOT drop all capabilities =="
kubectl get pods --all-namespaces -o json \
| jq -r '
.items[]
| {
ns: .metadata.namespace,
pod: .metadata.name,
containers: (
([.spec.containers[], (.spec.initContainers // [])[]]
| {
name: .name,
drop: (.securityContext.capabilities.drop // [] | map(.))
})
)
}
| select(
# problematic if any container does not drop ALL
(.containers[]?.drop | map(ascii_upcase) | index("ALL") | not)
)
| "\(.ns)"
' 2>/dev/null | sort -u || echo "Failed to summarize namespaces."
echo
# 4) Show namespaced policies that might be intended to enforce dropping capabilities
# (for review: PodSecurity, Gatekeeper, Kyverno, etc. labels/annotations)
echo "== Namespaces and Pod Security labels (Kubernetes Pod Security Standards) =="
kubectl get ns --show-labels
echo
echo "== Guidance =="
cat <<'EOF'
Interpretation:
1) Problematic capabilities usage:
- Any container showing a non-empty "add:" list is explicitly requesting extra Linux capabilities.
- Any container where "drop:" does NOT include "ALL" is potentially retaining capabilities.
Such pods will appear in the "Pods with capabilities configured" section.
2) Namespaces of concern:
- Namespaces listed under "Namespaces with pods that do NOT drop all capabilities"
contain at least one pod where a container does not drop ALL capabilities.
- For namespaces whose workloads do not require Linux capabilities, these are the
prime candidates where you should consider adding admission policy that forbids
pods unless they drop ALL capabilities.
3) Manual review:
- For each flagged namespace and pod, review whether the application truly needs
the capabilities being retained or added.
- For namespaces that should be "no-capabilities", implement or tighten admission
controls (e.g., Pod Security Standards, Gatekeeper/Kyverno policies) to reject
pods that do not drop ALL capabilities.
EOF
What output indicates a problem
-
In the “Pods with capabilities configured” section:
- Any
add:list that is not[]means the container is explicitly adding Linux capabilities. - Any
drop:list that is[]or does not containALLmeans the container is not dropping all capabilities.
- Any
-
In the “Namespaces with pods that do NOT drop all capabilities” section:
- Any namespace listed here contains pods where at least one container does not drop
ALLcapabilities; these namespaces should be reviewed, and where workloads do not require capabilities, admission policies should be considered to forbid such pods.
- Any namespace listed here contains pods where at least one container does not drop