Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 22 additions & 7 deletions skills/cloud/container-security/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -174,16 +184,17 @@ Produce the final report using the structure defined in the Output Format sectio
- **Line(s):** <line numbers>
- **Resource:** <Deployment/StatefulSet name>
- **Container:** <container name>
- **Container type:** regular / init / ephemeral
- **Description:** <what was found>
- **Evidence:** <specific configuration>
- **Remediation:** <fix with code example>

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

Expand Down Expand Up @@ -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.

---

Expand Down Expand Up @@ -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.
73 changes: 72 additions & 1 deletion skills/cloud/container-security/cis-benchmarks.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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:**

Expand Down Expand Up @@ -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.
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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"]