> ## Documentation Index
> Fetch the complete documentation index at: https://cloudanix.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Apply Security Context To Your Pods And Containers

### More Info:

Apply Security Context to Your Pods and Containers

### 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

<Tabs>
  <Tab title="Remediation">
    ### Remediation

    <AccordionGroup>
      <Accordion title="Manual Steps" defaultOpen="true">
        1. **List pods and identify those missing securityContext**
           * Run on: any machine with `kubectl` access
           ```bash theme={null}
           kubectl get pods --all-namespaces -o json \
           | jq -r '
             .items[]
             | {
                 ns: .metadata.namespace,
                 pod: .metadata.name,
                 podSC: .spec.securityContext,
                 cSC: ([.spec.containers[].securityContext] // []),
                 iSC: ([.spec.initContainers[].securityContext] // [])
               }
             | select(.podSC == null and ( .cSC | all(. == null) ) and ( .iSC | all(. == null) ))
             | [.ns, .pod] | @tsv
           ' | column -t
           ```
           * This lists pods with no pod-level or container-level securityContext defined.

        2. **Inspect security context details for a specific pod**
           * Run on: any machine with `kubectl` access
           ```bash theme={null}
           NAMESPACE=default
           POD_NAME=example-pod
           kubectl get pod "$POD_NAME" -n "$NAMESPACE" -o yaml \
           | yq '.spec | {securityContext, containers: [.containers[].name, .containers[].securityContext], initContainers: [.initContainers[].name, .initContainers[].securityContext]}'
           ```
           * Review which settings (runAsUser, runAsNonRoot, readOnlyRootFilesystem, capabilities, privileged, hostNetwork, hostPID, hostIPC, seccompProfile, etc.) are missing or overly permissive.

        3. **Review workload owners (Deployments, etc.) for missing or weak security contexts**
           * Run on: any machine with `kubectl` access
           ```bash theme={null}
           kubectl get deploy,sts,ds,job,cronjob -A -o yaml \
           | yq '
             .items[]
             | {
                 kind: .kind,
                 ns: .metadata.namespace,
                 name: .metadata.name,
                 podSC: .spec.template.spec.securityContext,
                 containers: [.spec.template.spec.containers[].securityContext],
                 initContainers: [.spec.template.spec.initContainers[].securityContext]
               }
           '
           ```
           * Identify templates that lack securityContext or set privileged: true, allow privilege escalation, broad capabilities, or host namespaces/paths.

        4. **Decide required security context based on app needs and org policy**
           * For each workload identified in steps 1–3, review with the app owner whether it can:
             * Run as non-root (runAsNonRoot: true, runAsUser: non-0 UID, runAsGroup)
             * Use a read-only root filesystem
             * Drop all capabilities and add back only specific required ones
             * Avoid privileged: true and avoid hostPath, hostNetwork, hostPID, hostIPC where possible
           * Refer to your org’s baseline and the CIS Google Container-Optimized OS Benchmark to choose appropriate defaults.

        5. **Update manifests to add or tighten securityContext**
           * Run on: any machine with `kubectl` access
           * Export current manifest, edit locally, then apply:
           ```bash theme={null}
           NAMESPACE=default
           WORKLOAD=example-deployment
           kubectl get deploy "$WORKLOAD" -n "$NAMESPACE" -o yaml > /tmp/"$WORKLOAD".yaml
           ```
           * In `/tmp/"$WORKLOAD".yaml`, under `.spec.template.spec` add or adjust, for example:
           ```yaml theme={null}
           securityContext:
             runAsNonRoot: true
             runAsUser: 1000
             runAsGroup: 1000
             fsGroup: 2000
           containers:
             - name: app
               securityContext:
                 allowPrivilegeEscalation: false
                 readOnlyRootFilesystem: true
                 privileged: false
                 capabilities:
                   drop: ["ALL"]
           ```
           * Then apply:
           ```bash theme={null}
           kubectl apply -f /tmp/"$WORKLOAD".yaml
           ```

        6. **Re-verify that pods now have appropriate security contexts**
           * Run on: any machine with `kubectl` access
           ```bash theme={null}
           kubectl get pods --all-namespaces -o json \
           | jq -r '
             .items[]
             | select(.spec.securityContext == null
                      and ([.spec.containers[].securityContext] // [] | all(. == null))
                      and ([.spec.initContainers[].securityContext] // [] | all(. == null)))
             | [.metadata.namespace, .metadata.name] | @tsv
           ' | column -t
           ```
           * Confirm that critical workloads are no longer listed, and spot-check updated pods with:
           ```bash theme={null}
           kubectl get pod "$POD_NAME" -n "$NAMESPACE" -o yaml | yq '.spec'
           ```
      </Accordion>

      <Accordion title="Using kubectl">
        ```bash theme={null}
        # 1) List all pods and their security context usage (namespaces, pod & container level)
        # Run on: any machine with kubectl access
        kubectl get pods --all-namespaces -o custom-columns=\
        NAMESPACE:.metadata.namespace,\
        POD:.metadata.name,\
        POD_SC:.spec.securityContext,\
        CONTAINERS_SC:.spec.containers[*].securityContext
        ```

        Problem indication:

        * `POD_SC` is `<none>` for most pods, and
        * `CONTAINERS_SC` is `<none>` or `{}` (empty) for most containers.\
          This shows security context is largely not defined.

        ***

        ```bash theme={null}
        # 2) Inspect full spec for specific pods (e.g., application namespaces)
        # Replace <namespace> and <pod-name> with actual values from your cluster
        kubectl -n <namespace> get pod <pod-name> -o yaml
        ```

        In the output, focus on:

        * `.spec.securityContext` (pod-level)
        * `.spec.containers[*].securityContext`
        * `.spec.initContainers[*].securityContext` (if present)

        Problem indication:

        * Missing `securityContext` blocks entirely.
        * Present but empty securityContext `{}` with no meaningful fields.
        * Risky settings, for example:
          * `runAsUser: 0` or `runAsNonRoot: false`
          * `privileged: true`
          * `allowPrivilegeEscalation: true`
          * Broad `capabilities.add` (e.g., `SYS_ADMIN`, `NET_ADMIN`).

        ***

        ```bash theme={null}
        # 3) Identify containers running as root or lacking non-root guarantees
        kubectl get pods --all-namespaces -o jsonpath='
        {range .items[*]}
        {.metadata.namespace}{"\t"}{.metadata.name}{"\t"}
        {range .spec.containers[*]}
        {"runAsUser="}{.securityContext.runAsUser}{" "}
        {"runAsNonRoot="}{.securityContext.runAsNonRoot}{" "}
        {"privileged="}{.securityContext.privileged}{" "}
        {"allowPrivilegeEscalation="}{.securityContext.allowPrivilegeEscalation}{"; "}
        {end}{"\n"}
        {end}'
        ```

        Problem indication (requires human review):

        * `runAsUser=` is empty and `runAsNonRoot=` is empty/false (likely root).
        * `privileged=true` or `allowPrivilegeEscalation=true` without a strong justification.

        ***

        ```bash theme={null}
        # 4) Show pods with any privileged container
        kubectl get pods --all-namespaces -o json | \
        jq -r '
          .items[]
          | {ns: .metadata.namespace, pod: .metadata.name, containers: .spec.containers}
          | select(.containers[]?.securityContext?.privileged == true)
          | "\(.ns)\t\(.pod)"
        '
        ```

        Problem indication:

        * Any application or multi-tenant workload appears in this list without a clear, documented need to be privileged.

        ***

        ```bash theme={null}
        # 5) Show pods where allowPrivilegeEscalation is true or unset
        kubectl get pods --all-namespaces -o json | \
        jq -r '
          .items[]
          | {ns: .metadata.namespace, pod: .metadata.name, containers: .spec.containers}
          | select(
              [.containers[]? | .securityContext.allowPrivilegeEscalation] 
              | any(. == true or . == null)
            )
          | "\(.ns)\t\(.pod)"
        '
        ```

        Problem indication:

        * Application pods listed here generally need stricter `securityContext` (e.g., `allowPrivilegeEscalation: false`) unless there is a specific requirement.

        ***

        These commands only surface current state. A human must decide, per workload, which security context fields to add or tighten based on application needs and your organization’s security policy.
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        #
        # Report pods and containers that lack recommended securityContext settings.
        # Run on any machine with kubectl access and current context set.
        #
        # This is a read-only assessment. It does NOT change the cluster.

        set -euo pipefail

        # Fail fast if kubectl is not available or cannot reach the cluster
        kubectl version --short >/dev/null 2>&1 || {
          echo "ERROR: kubectl not available or cannot reach the cluster" >&2
          exit 1
        }

        echo "Collecting pod securityContext information from all namespaces..."
        echo

        # Headers
        printf "%-32s %-24s %-40s %-12s %-7s %-7s %-9s %-11s %-11s %-11s %-9s %-9s\n" \
          "NAMESPACE" "POD" "CONTAINER" "TYPE" "UID" "GID" "PRIVILEGED" "HOSTPID" "HOSTIPC" "HOSTNET" "ROFS" "DROPCAPS"

        # Explanation of columns (for later review)
        cat <<'EOF'

        COLUMN MEANING (a blank/empty value is what you need to review):
          UID        : runAsUser (effective user ID)
          GID        : runAsGroup or fsGroup (effective group ID)
          PRIVILEGED : container.securityContext.privileged
          HOSTPID    : pod.spec.hostPID
          HOSTIPC    : pod.spec.hostIPC
          HOSTNET    : pod.spec.hostNetwork
          ROFS       : container.securityContext.readOnlyRootFilesystem
          DROPCAPS   : whether NET_RAW (and other caps) are dropped

        Rows where UID/GID/ROFS/DROPCAPS are empty or PRIVILEGED/HOST* are "true"
        indicate items to review against your security policy.

        EOF

        # Use a single JSON query and format in bash for readability at scale
        kubectl get pods -A -o json \
        | jq -r '
          .items[]
          | . as $pod
          | (
              # pod-level fields
              .metadata.namespace as $ns
              | .metadata.name as $podName
              | (.spec.securityContext // {}) as $psc
              | (.spec.hostPID // false) as $hostPID
              | (.spec.hostIPC // false) as $hostIPC
              | (.spec.hostNetwork // false) as $hostNet
              | ($psc.runAsUser // empty) as $podUid
              | ($psc.runAsGroup // empty) as $podGid
              | ($psc.fsGroup // empty) as $podFsGroup
              | .spec.containers[]
              | .name as $cname
              | (.securityContext // {}) as $csc
              | ($csc.runAsUser // $podUid // empty) as $uid
              | ($csc.runAsGroup // $podGid // empty) as $gid
              | ($psc.fsGroup // $podFsGroup // empty) as $fsgid
              | ($csc.privileged // false) as $priv
              | ($csc.readOnlyRootFilesystem // empty) as $rofs
              | (($csc.capabilities.drop // []) | map(select(. == "NET_RAW")) | length > 0) as $dropNetRaw
              | (($csc.capabilities.drop // []) | length > 0) as $dropAnyCap
              | [
                  $ns,
                  $podName,
                  $cname,
                  "main",
                  (if $uid|tostring == "null" then "" else ($uid|tostring) end),
                  (if $gid|tostring == "null" then "" else ($gid|tostring) end),
                  (if $priv then "true" else "false" end),
                  (if $hostPID then "true" else "false" end),
                  (if $hostIPC then "true" else "false" end),
                  (if $hostNet then "true" else "false" end),
                  (if $rofs|tostring == "null" then "" else ($rofs|tostring) end),
                  (if $dropAnyCap then (if $dropNetRaw then "yes+NET_RAW" else "yes" end) else "" end)
                ]
            )
          | @tsv
        ' \
        | while IFS=$'\t' read -r ns pod cname type uid gid priv hostpid hostipc hostnet rofs dropcaps; do
            printf "%-32s %-24s %-40s %-12s %-7s %-7s %-9s %-11s %-11s %-11s %-9s %-9s\n" \
              "$ns" "$pod" "$cname" "$type" "$uid" "$gid" "$priv" "$hostpid" "$hostipc" "$hostnet" "$rofs" "$dropcaps"
          done

        cat <<'EOF'

        HOW TO INTERPRET POTENTIAL PROBLEMS:

        Review rows where:
          - UID and/or GID are empty:
              No explicit runAsUser/runAsGroup configured at pod or container level.
          - ROFS is empty or "false":
              Root filesystem is writable for the container.
          - DROPCAPS is empty:
              No Linux capabilities explicitly dropped (e.g., NET_RAW).
          - PRIVILEGED is "true":
              Privileged container – only allow if strongly justified.
          - HOSTPID / HOSTIPC / HOSTNET are "true":
              Pod shares host namespaces – only allow if strongly justified.

        Use this report to:
          1. Identify high‑risk pods/containers.
          2. Review their manifests/Helm charts against your security standards.
          3. Add or tighten securityContext where appropriate (pod and/or container level).

        Note: This script only reports state; applying securityContext changes must be done
        manually through your normal deployment workflow (manifests, Helm, GitOps, etc.).
        EOF
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>

### Additional Reading:

* [https://kubernetes.io/docs/concepts/policy/security-context/](https://kubernetes.io/docs/concepts/policy/security-context/)
