Skip to main content

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

Manual Steps
  1. 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).
  2. 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 capAdd entries and for containers that do not specify drop: ["ALL"].
  3. Decide which workloads actually need capabilities

    • For each container with capAdd (or no drop: ["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.
  4. 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 forbid capAdd except for explicitly allowed cases. For example, using Kyverno (on any machine with kubectl access):
      kubectl apply -f - << 'EOF'
      apiVersion: kyverno.io/v1
      kind: ClusterPolicy
      metadata:
      name: require-drop-all-capabilities
      spec:
      validationFailureAction: enforce
      rules:
      - name: require-drop-all
      match:
      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 allowed
      EOF
    • Adjust the example to your policy engine and list of target namespaces; review carefully before enforcing in production.
  5. 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):
      kubectl -n TARGET_NS get deploy APP_NAME -o yaml > APP_NAME-deploy.yaml
      Edit APP_NAME-deploy.yaml to include, under each container:
      securityContext:
      capabilities:
      drop:
      - "ALL"
      Then apply:
      kubectl apply -f APP_NAME-deploy.yaml
    • For pods created by other controllers (CronJobs, Jobs, Operators), update the relevant higher-level resource templates similarly.
  6. 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.add present with any capability values.
  • No securityContext.capabilities.drop and 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:

  • allowedCapabilities contains capabilities beyond what is needed, especially *.
  • requiredDropCapabilities is empty or does not include ALL for 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 privileged or 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.capabilities for 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.add with capabilities like NET_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 contain ALL means the container is not dropping all capabilities.
  • 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 ALL capabilities; these namespaces should be reviewed, and where workloads do not require capabilities, admission policies should be considered to forbid such pods.

Additional Reading: