Skip to main content

Minimize The Admission Containers With Capabilities Assigned

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 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. List all pods and identify those adding capabilities

    • Run on: any machine with kubectl access
    kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{range .spec.containers[*]}{.name}{" "}{.securityContext.capabilities}{";"}{end}{"\n"}{end}' \
    | grep -v "{}" || true
    • Review the output for containers that define add capabilities or do not drop: ["ALL"].
  2. Inspect manifests for each affected workload

    • For each namespace with pods showing capabilities, inspect the controlling object (Deployment, DaemonSet, StatefulSet, Job, etc.):
    kubectl get deploy,ds,sts,job,cronjob -n <namespace> -o yaml > /tmp/workloads-<namespace>.yaml
    • In the dumped file, search for capabilities:, add:, and drop: and note which applications are using which capabilities and why.
  3. Decide required vs. excess capabilities with app owners

    • For each workload using capabilities, compare the listed capabilities against documented application requirements and least-privilege principles.
    • Mark each capability as: required (cannot drop without breaking functionality) or excess (can be dropped).
    • Prefer configurations where containers explicitly drop: ["ALL"] and only re-add strictly necessary individual capabilities.
  4. Tighten securityContext in manifests

    • For workloads that do not need any capabilities, update their manifests (in your Git/IaC source, not just live) so each container’s securityContext includes:
    securityContext:
    capabilities:
    drop:
    - "ALL"
    • For workloads needing a small set of capabilities, configure:
    securityContext:
    capabilities:
    drop:
    - "ALL"
    add:
    - "NET_BIND_SERVICE" # example; use only what is required
    • Apply the updated manifests:
    kubectl apply -f <your-updated-manifests>.yaml
  5. Optionally enforce namespace-level policy (PSP replacement)

    • If you have namespaces where no workloads should use Linux capabilities, define and apply a restrictive policy (e.g., PodSecurity admission restricted profile or an equivalent Gatekeeper/Kyverno policy) that effectively forbids adding capabilities and requires drop: ["ALL"].
    • Apply with kubectl on any machine with cluster access:
    kubectl apply -f <restrict-capabilities-policy>.yaml
  6. Verify the current state matches your decisions

    • Re-run the discovery and confirm that only workloads you intentionally approved have capabilities, and that namespaces meant to forbid capabilities have none:
    kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{range .spec.containers[*]}{.name}{" "}{.securityContext.capabilities}{";"}{end}{"\n"}{end}' \
    | grep -v "{}" || true
    • Confirm that in “no-capabilities” namespaces, the output is empty or shows drop: ["ALL"] with no add entries.
Using kubectl

Using kubectl

Run these from any machine with kubectl access.

1. Find pods explicitly using Linux capabilities

kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}{" "}
{.metadata.name}{"\n"}{range .spec.containers[*]}{" container: "}{.name}{"\n"}
{" capabilities add: "}{.securityContext.capabilities.add}{"\n"}
{" capabilities drop: "}{.securityContext.capabilities.drop}{"\n"}{end}{"\n"}{end}' \
| sed '/capabilities add: <nil>/d'

Problem indication:

  • Any container showing capabilities add: [...] is explicitly requesting extra capabilities.
  • Pay special attention when:
    • drop is empty or missing.
    • add includes broad capabilities like ALL, NET_ADMIN, SYS_ADMIN, DAC_OVERRIDE, etc.
  • In namespaces where workloads do not need special Linux capabilities, any non‑empty add is suspicious.

2. Check deployments/statefulsets/daemonsets for capabilities in pod specs

Deployments:

kubectl get deploy -A -o yaml | grep -nE 'capabilities:|add:|drop:' -n

StatefulSets:

kubectl get statefulset -A -o yaml | grep -nE 'capabilities:|add:|drop:' -n

DaemonSets:

kubectl get daemonset -A -o yaml | grep -nE 'capabilities:|add:|drop:' -n

Problem indication:

  • Any pod template defining securityContext.capabilities.add needs review.
  • Look for patterns where:
    • Capabilities are added but no capabilities are dropped.
    • The same elevated set appears across many workloads or namespaces, suggesting over‑permissive defaults.

3. Identify namespaces likely not needing Linux capabilities

kubectl get ns

Then, for each non‑infrastructure namespace (e.g., your app namespaces):

kubectl get pods -n <namespace> -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}
{range .spec.containers[*]}{" container: "}{.name}{"\n"}
{" capabilities add: "}{.securityContext.capabilities.add}{"\n"}
{" capabilities drop: "}{.securityContext.capabilities.drop}{"\n"}{end}{"\n"}{end}' \
| sed '/capabilities add: <nil>/d'

Problem indication:

  • In namespaces where applications are simple web/API/batch jobs and do not require host‑level operations, any added capability is likely unnecessary and should be questioned.

4. Check for cluster‑level defaults increasing capabilities (PodSecurityPolicies, if present)

If your cluster still uses PodSecurityPolicy:

kubectl get psp -o yaml | grep -nE 'allowedCapabilities:|defaultAddCapabilities:|requiredDropCapabilities:' -n

Problem indication:

  • allowedCapabilities: ["*"] or including powerful capabilities.
  • defaultAddCapabilities set to anything other than an empty list.
  • Absence of requiredDropCapabilities: ["ALL"] (or similar strong default) in namespaces where no capabilities are needed.

5. (Optional) Inspect Pod Security admission (if used) for capability rules

If using built‑in Pod Security admission via labels:

kubectl get ns --show-labels

Problem indication:

  • Namespaces not using pod-security.kubernetes.io/enforce=restricted (or stricter) may allow capabilities that the restricted profile would otherwise prevent.
  • This does not directly show capabilities, but highlights namespaces where capability use is less constrained and needs closer examination in steps 1–3.
Automation
#!/usr/bin/env bash
#
# Report pods/containers that add Linux capabilities or fail to drop all capabilities.
# Run on: any machine with kubectl access and current-context pointing at the target cluster.

set -euo pipefail

# Header
echo "Scanning cluster for non-default Linux capabilities on containers..."
echo

# 1) List all pods with any explicitly added capabilities
echo "=== Pods with explicitly ADDED capabilities (potentially risky) ==="
kubectl get pods -A -o json \
| jq -r '
.items[]
| .metadata as $meta
| ( .spec.initContainers // [] + .spec.containers // [] )[]
| select(.securityContext.capabilities.add != null and (.securityContext.capabilities.add | length > 0))
| .name as $cname
| $meta.namespace as $ns
| $meta.name as $pname
| .securityContext.capabilities.add as $add
| "NAMESPACE=\($ns)\tPOD=\($pname)\tCONTAINER=\($cname)\tADDED_CAPS=\($add | join(\",\"))"
' 2>/dev/null || echo "Error: jq not installed or kubectl error."

echo
echo "NOTE: Any line above indicates a container that explicitly ADDS Linux capabilities."
echo " Review whether each listed capability is strictly required by the workload."
echo

# 2) List pods that do NOT drop all capabilities in namespaces that might not need them
# (i.e., no 'drop: [\"ALL\"]' present)
echo "=== Pods WITHOUT 'drop: [\"ALL\"]' on capabilities (for review) ==="
kubectl get pods -A -o json \
| jq -r '
.items[]
| .metadata as $meta
| ( .spec.initContainers // [] + .spec.containers // [] )[]
| .name as $cname
| $meta.namespace as $ns
| $meta.name as $pname
| .securityContext.capabilities as $caps
| select(
# Select containers that either have no capabilities block
# or have a capabilities block but do NOT drop ALL.
($caps == null)
or
(
($caps.drop // []) as $drops
| ( [$drops[]? | select(. == "ALL")] | length ) == 0
)
)
| "NAMESPACE=\($ns)\tPOD=\($pname)\tCONTAINER=\($cname)\tCAPS_BLOCK=\($caps)"
' 2>/dev/null || echo "Error: jq not installed or kubectl error."

cat <<'EOF'

INTERPRETING THE OUTPUT
-----------------------
1) "Pods with explicitly ADDED capabilities":
- Any line here is a clear hotspot. These containers request additional Linux
capabilities beyond the default set.
- Problem indicators:
* Sensitive capabilities such as NET_ADMIN, SYS_ADMIN, SYS_MODULE, DAC_READ_SEARCH,
SYS_PTRACE, MKNOD, NET_RAW, etc.
* Generic use of many capabilities without clear justification.

2) "Pods WITHOUT 'drop: [\"ALL\"]' on capabilities":
- This is a broader review list. It includes containers that:
* Do not define a capabilities block at all (inherit default capabilities), or
* Define capabilities but do NOT drop ALL.
- For namespaces/applications that do NOT need any Linux capabilities, you should:
* Expect these containers to have securityContext.capabilities.drop: ["ALL"] (ideally
enforced by a PodSecurityPolicy/Pod Security Admission / admission controller).
* Any line here in such namespaces is a potential problem: the container has not
explicitly dropped all capabilities and may be running with more privileges than required.

REVIEW GUIDANCE
---------------
- For each namespace, decide whether workloads truly need Linux capabilities.
- For namespaces that do NOT need capabilities:
* All lines in the second section for that namespace are candidates for remediation:
adjust pod specs (or higher-level controllers) so containers explicitly drop ALL
capabilities and do not add new ones.
- This script does NOT automatically fix anything; it only surfaces where capabilities are
explicitly added, or where "drop: [\"ALL\"]" is missing so you can apply policy (e.g.,
PodSecurityPolicy equivalent / Pod Security Admission / other admission controls) and
update manifests accordingly.
EOF

Additional Reading: