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:​