diff --git a/skills/cloud/container-security/SKILL.md b/skills/cloud/container-security/SKILL.md index eb43ecf0..4c797470 100644 --- a/skills/cloud/container-security/SKILL.md +++ b/skills/cloud/container-security/SKILL.md @@ -13,7 +13,7 @@ phase: [build, deploy, operate] frameworks: [CIS-Docker-v1.6.0, CIS-Kubernetes-v1.9.0, NIST-SP-800-190] difficulty: intermediate time_estimate: "30-60min" -version: "1.0.0" +version: "1.1.0" author: unitoneai license: MIT allowed-tools: Read, Grep, Glob @@ -101,10 +101,20 @@ Use Glob to locate all relevant configuration files. **/*-rbac.yaml **/*-psp.yaml **/*-podsecuritypolicy.yaml +**/*ephemeralcontainer*.yaml +**/*debug*.yaml ``` Classify findings by type: Dockerfiles, Kubernetes manifests, Helm charts, Kustomize overlays, and supporting configs. Record all discovered files. +For Kubernetes workloads, inventory every container array separately: + +- `spec.containers` +- `spec.initContainers` +- `spec.ephemeralContainers` + +Treat `ephemeralContainers` as a security-relevant debug surface even though they are usually added through the `pods/ephemeralcontainers` subresource rather than declared in the original workload manifest. If debug-container evidence is unavailable, mark ephemeral-container coverage as **Not Evaluable** instead of assuming the workload is Restricted-compliant. + --- ### Step 2 through Step 6: CIS Benchmark and NIST SP 800-190 Evaluation @@ -174,16 +184,17 @@ Produce the final report using the structure defined in the Output Format sectio - **Line(s):** - **Resource:** - **Container:** +- **Container type:** regular / init / ephemeral - **Description:** - **Evidence:** - **Remediation:** ### Pod Security Standards Compliance Matrix -| Workload | Namespace | PSS Level | Violations | -|----------|-----------|-----------|------------| -| deploy/app | production | Baseline (not Restricted) | runAsRoot, no seccomp | -| deploy/worker | production | Privileged | privileged: true | +| Workload | Namespace | PSS Level | Regular Containers | Init Containers | Ephemeral Containers | Violations | +|----------|-----------|-----------|--------------------|-----------------|----------------------|------------| +| deploy/app | production | Baseline (not Restricted) | Reviewed | Reviewed | Not Evaluable | runAsRoot, no seccomp | +| pod/debug-target | production | Privileged | Reviewed | None | Reviewed | ephemeral container privileged: true | ### Prioritized Remediation Plan @@ -246,17 +257,20 @@ Produce the final report using the structure defined in the Output Format sectio | runAsNonRoot | -- | Must be true | | seccompProfile | -- | RuntimeDefault or Localhost | +Apply the container-level controls to `containers`, `initContainers`, and `ephemeralContainers`. A Restricted workload is not fully evaluated unless all three container arrays are checked or explicitly marked absent / Not Evaluable. + --- ## Common Pitfalls -1. **Init containers and sidecar containers are often missed.** Pod Security Standards apply to ALL containers in a pod, including init containers and ephemeral containers. Check every container spec. +1. **Init, sidecar, and ephemeral containers are often missed.** Pod Security Standards apply to ALL containers in a pod, including init containers and ephemeral containers. Check every container spec and record whether debug/ephemeral-container evidence was available. 2. **Helm template values may override security settings.** A Helm chart template may set `runAsNonRoot: true`, but `values.yaml` or environment-specific values files may override it to `false`. Always check both the templates and all values files. 3. **Default namespace is not just a naming issue.** The `default` namespace typically has no NetworkPolicy and no Pod Security Admission labels. Workloads in `default` often bypass all policy controls. 4. **Base64 encoding is not encryption.** Kubernetes Secrets store data as base64, which is trivially decodable. Secrets committed to version control in manifests are effectively plaintext. 5. **`readOnlyRootFilesystem` breaks many applications.** When recommending this control, also recommend adding writable `emptyDir` volume mounts for directories the application needs to write to (e.g., `/tmp`, `/var/cache`). 6. **Network policies are additive, not subtractive.** A default-deny policy must be explicitly created. Without it, all pod-to-pod traffic is allowed regardless of other NetworkPolicy resources. -7. **Distroless images have no shell.** While this is excellent for security, note that debugging requires ephemeral containers (`kubectl debug`). Flag this as a consideration, not a problem. +7. **Distroless images have no shell.** While this is excellent for security, note that debugging often uses ephemeral containers (`kubectl debug`). Flag the need for debug workflow evidence, not the distroless image itself. +8. **Debug containers can bypass the reviewed deployment manifest.** A workload manifest may be Restricted-compliant while an operator later injects a privileged ephemeral container into a running pod. Ask for admission-policy coverage of the `pods/ephemeralcontainers` subresource, RBAC on `pods/ephemeralcontainers`, and audit events for debug-container creation. --- @@ -294,3 +308,4 @@ Produce the final report using the structure defined in the Output Format sectio ## Changelog - **1.0.0** -- Initial release. Full coverage of CIS Docker Benchmark v1.6.0 Section 4-5, CIS Kubernetes Benchmark v1.9.0 Sections 1-5, and NIST SP 800-190 countermeasures across all five risk categories. +- **1.1.0** -- Added explicit ephemeral/debug container evidence requirements for Pod Security Standards review, including container inventory, report fields, and debug subresource coverage. diff --git a/skills/cloud/container-security/cis-benchmarks.md b/skills/cloud/container-security/cis-benchmarks.md index 3b547ca4..80548cc3 100644 --- a/skills/cloud/container-security/cis-benchmarks.md +++ b/skills/cloud/container-security/cis-benchmarks.md @@ -264,6 +264,14 @@ Evaluate workload configurations against Kubernetes Pod Security Standards. The | **Baseline** | Minimally restrictive. Prevents known privilege escalations. | Standard workloads | | **Restricted** | Heavily restricted. Follows current hardening best practices. | Security-sensitive and untrusted workloads | +**Container inventory gate:** For every Pod template or Pod object, review all three container arrays: + +- `spec.containers` +- `spec.initContainers` +- `spec.ephemeralContainers` + +Container-level Pod Security Standards controls apply to all three. A manifest that hardens only `containers` but misses `initContainers` or `ephemeralContainers` is incomplete. If ephemeral containers are managed only at runtime through the `pods/ephemeralcontainers` subresource, collect RBAC, admission-policy, and audit-log evidence for that subresource or mark the check **Not Evaluable**. + #### CIS 5.2.1 -- Ensure that the cluster has at least one active policy control mechanism installed Check for Pod Security Admission labels on namespaces: @@ -332,6 +340,8 @@ spec: **Grep pattern:** Check for absence of `allowPrivilegeEscalation: false` on all containers. +Apply this to `containers[*]`, `initContainers[*]`, and `ephemeralContainers[*]`. + #### CIS 5.2.7 -- Minimize the admission of root containers ```yaml @@ -406,6 +416,65 @@ ports: hostPort: 8080 # FAIL: binds directly to host ``` +#### Ephemeral/debug container evidence gate + +Ephemeral containers are temporary containers added to an existing Pod for debugging. They are usually created via `kubectl debug` and the `pods/ephemeralcontainers` subresource, so they may not appear in the original Deployment, StatefulSet, DaemonSet, Job, or CronJob manifest. + +**Missed vulnerable pattern:** + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: checkout-api +spec: + containers: + - name: app + image: registry.example.com/checkout-api@sha256:... + securityContext: + runAsNonRoot: true + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: RuntimeDefault + ephemeralContainers: + - name: node-debug + image: busybox:1.36 + targetContainerName: app + securityContext: + privileged: true + runAsUser: 0 + allowPrivilegeEscalation: true + capabilities: + add: ["SYS_ADMIN"] +``` + +The regular container is Restricted-like, but the debug container violates the same PSS controls. Report this as a privileged ephemeral container, not as a clean workload. + +**Evidence to request when ephemeral containers are not present in manifests:** + +| Evidence | What to verify | +|---|---| +| RBAC for `pods/ephemeralcontainers` | Only authorized break-fix roles can create/update ephemeral containers | +| Admission policy | Pod Security Admission, Kyverno, Gatekeeper, or equivalent evaluates the `ephemeralcontainers` subresource | +| Audit events | `update` or `patch` calls to `pods/ephemeralcontainers` are logged with user, namespace, pod, image, target container, and security context | +| Debug image policy | Debug images are pinned, approved, and scanned; no arbitrary image pull for production debug | +| Runtime controls | Privileged, host namespace, hostPath, extra capabilities, non-default procMount, and root user are rejected or explicitly exception-approved | + +**Review checks:** + +``` +PSS-EPHEMERAL-01: `ephemeralContainers[*].securityContext.privileged` is not true +PSS-EPHEMERAL-02: `ephemeralContainers[*].securityContext.allowPrivilegeEscalation` is false for Restricted workloads +PSS-EPHEMERAL-03: `ephemeralContainers[*].securityContext.capabilities.drop` includes ALL and added capabilities are limited +PSS-EPHEMERAL-04: `ephemeralContainers[*].securityContext.runAsNonRoot` is true or `runAsUser` is non-root +PSS-EPHEMERAL-05: `ephemeralContainers[*].securityContext.seccompProfile.type` is RuntimeDefault or Localhost +PSS-EPHEMERAL-06: RBAC restricts create/update on `pods/ephemeralcontainers` +PSS-EPHEMERAL-07: Admission policy covers the `pods/ephemeralcontainers` subresource, not only normal pod create/update +PSS-EPHEMERAL-08: Debug-container creation is audited and alertable in production namespaces +``` + ### CIS 5.3 -- Network Policies and CNI #### CIS 5.3.1 -- Ensure that the CNI in use supports NetworkPolicies @@ -648,7 +717,7 @@ securityContext: ## Comprehensive Security Context Evaluation -For each workload (Deployment, StatefulSet, DaemonSet, Job, CronJob), evaluate the complete security context against the Restricted Pod Security Standard. +For each workload (Deployment, StatefulSet, DaemonSet, Job, CronJob) and for standalone Pod objects, evaluate the complete security context against the Restricted Pod Security Standard. Include `containers`, `initContainers`, and `ephemeralContainers`. **Restricted PSS Requirements Checklist:** @@ -690,3 +759,5 @@ spec: - Capabilities beyond the allowed set (only `NET_BIND_SERVICE` is permitted) - `procMount` other than `Default` - `appArmorProfile` of `unconfined` + +Container-level fields must be checked under `containers[*]`, `initContainers[*]`, and `ephemeralContainers[*]`. Report `ephemeralContainers: Not Evaluable` when runtime debug-container evidence is unavailable. diff --git a/skills/cloud/container-security/tests/benign/ephemeral-container-restricted.yaml b/skills/cloud/container-security/tests/benign/ephemeral-container-restricted.yaml new file mode 100644 index 00000000..43aad123 --- /dev/null +++ b/skills/cloud/container-security/tests/benign/ephemeral-container-restricted.yaml @@ -0,0 +1,34 @@ +apiVersion: v1 +kind: Pod +metadata: + name: checkout-api + namespace: production +spec: + securityContext: + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + containers: + - name: app + image: registry.example.com/checkout-api@sha256:2222222222222222222222222222222222222222222222222222222222222222 + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + runAsNonRoot: true + capabilities: + drop: ["ALL"] + seccompProfile: + type: RuntimeDefault + ephemeralContainers: + - name: node-debug + image: registry.example.com/debug-tools@sha256:3333333333333333333333333333333333333333333333333333333333333333 + targetContainerName: app + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + runAsNonRoot: true + runAsUser: 1000 + capabilities: + drop: ["ALL"] + seccompProfile: + type: RuntimeDefault diff --git a/skills/cloud/container-security/tests/vulnerable/ephemeral-container-privileged.yaml b/skills/cloud/container-security/tests/vulnerable/ephemeral-container-privileged.yaml new file mode 100644 index 00000000..4738d7d0 --- /dev/null +++ b/skills/cloud/container-security/tests/vulnerable/ephemeral-container-privileged.yaml @@ -0,0 +1,30 @@ +apiVersion: v1 +kind: Pod +metadata: + name: checkout-api + namespace: production +spec: + securityContext: + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + containers: + - name: app + image: registry.example.com/checkout-api@sha256:1111111111111111111111111111111111111111111111111111111111111111 + securityContext: + allowPrivilegeEscalation: false + runAsNonRoot: true + capabilities: + drop: ["ALL"] + seccompProfile: + type: RuntimeDefault + ephemeralContainers: + - name: node-debug + image: busybox:1.36 + targetContainerName: app + securityContext: + privileged: true + runAsUser: 0 + allowPrivilegeEscalation: true + capabilities: + add: ["SYS_ADMIN"]