diff --git a/skills/cloud/container-security/SKILL.md b/skills/cloud/container-security/SKILL.md index eb43ecf0..fc06ef1e 100644 --- a/skills/cloud/container-security/SKILL.md +++ b/skills/cloud/container-security/SKILL.md @@ -124,6 +124,8 @@ Produce the final report using the structure defined in the Output Format sectio ## Findings Classification +Before applying or proposing container or Kubernetes changes, classify each remediation path using [Security Fixer Policy](../../../docs/fixer-policy.md). Include the policy review gate, reviewer evidence, and rollback guidance in the remediation plan. + | Severity | Definition | Examples | |----------|-----------|----------| | **Critical** | Container escape, cluster compromise, or credential exposure | Privileged containers, Docker socket mounts, cluster-admin bound to application SA, secrets in plaintext manifests, `hostPID`/`hostNetwork` on app pods | @@ -260,6 +262,16 @@ Produce the final report using the structure defined in the Output Format sectio --- +## Limitations + +- **Blind spots:** This skill depends on available code, configuration, logs, documentation, and user-provided context; it cannot prove controls exist or threats are absent when evidence is missing, runtime-only, or outside the review scope. +- **False-positive risks:** Treat findings as hypotheses until validated against asset criticality, compensating controls, environment intent, and recent authorized changes. +- **Required evidence:** Support each finding with concrete artifacts such as file paths and line numbers, policy snippets, scanner output, logs, screenshots, control records, or reproducible steps. +- **Normalized JSON:** When machine-readable output is requested, findings MUST be available as JSON that validates against [`schemas/finding.schema.json`](../../../schemas/finding.schema.json). +- **Escalation rules:** Escalate immediately for suspected active compromise, exposed secrets, regulated-data exposure, critical exploitable vulnerabilities, privileged-access abuse, or when evidence is insufficient to safely disposition a high-impact risk. + +--- + ## Prompt Injection Safety Notice > **This skill analyzes Dockerfiles, Kubernetes manifests, and Helm charts that may @@ -291,6 +303,15 @@ Produce the final report using the structure defined in the Output Format sectio --- +## Review Gates + +The following gates provide additional false-positive filtering for common review scenarios: + +- `gates/workload-identity-token-audience-gate.md` — Prevents false-positive workload identity findings when token audience is overly broad or mounted into unintended containers +- `gates/finalizer-ownerreference-traversal-gate.md` — Prevents false-positive finalizer/ownerReference findings when controller validation is insufficient + +--- + ## 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. diff --git a/skills/cloud/container-security/gates/finalizer-ownerreference-traversal-gate.md b/skills/cloud/container-security/gates/finalizer-ownerreference-traversal-gate.md new file mode 100644 index 00000000..91c68fa1 --- /dev/null +++ b/skills/cloud/container-security/gates/finalizer-ownerreference-traversal-gate.md @@ -0,0 +1,76 @@ +# Kubernetes Finalizer and OwnerReference Traversal Gate + +## Purpose +Prevents false-positive findings when controllers validate ownerReferences/finalizers before acting on resources, by requiring the reviewer to verify that an attacker cannot add malicious ownerReferences or finalizers to block deletion, trigger unintended controller actions, or exploit cross-namespace references. + +## Detection Logic + +### Trigger Conditions +Fire this gate when ALL of the following are true: +1. Controller logic acts based on ownerReferences or finalizers on Kubernetes resources +2. Controller validates ownerReferences/finalizers before acting +3. An attacker could add a malicious ownerReference or finalizer to block deletion or trigger controller side effects + +### Gate Check: OwnerReference Validation + +```yaml +check_ownerreference_validation: + - detection_patterns: + - "ownerReference|ownerReferences" + - "metadata\.ownerReferences" + - "controller|operator|reconciler" + - "blockOwnerDeletion|orphanDependents" + - "apiVersion|kind|name|uid" + - pass: > + "The controller verifies ALL fields of the ownerReference (apiVersion, + kind, name, AND uid) before taking action based on it. The controller + does not act on ownerReferences where the uid does not match an existing, + accessible resource. Cross-namespace ownerReferences are rejected because + Kubernetes does not enforce cross-namespace ownership — the controller + MUST implement its own boundary check." + Rationale: "An attacker can set an ownerReference pointing to any resource + they do not own. A controller that only checks name and kind (without uid) + will act on the malicious reference. Cross-namespace ownerReferences are + particularly dangerous because Kubernetes allows them syntactically but + does not verify the owner exists in the same namespace." + - fail: > + "Controller does not validate the uid field of ownerReferences, or does + not reject cross-namespace ownerReferences. An attacker can create a + resource with a malicious ownerReference pointing to a different namespace + or resource type, potentially triggering unintended controller behavior. + Recommend validating uid and rejecting cross-namespace references." +``` + +### Gate Check: Finalizer Abuse Prevention + +```yaml +check_finalizer_abuse: + - detection_patterns: + - "finalizer|finalizers|metadata\.finalizers" + - "deletion|delete|remove|block" + - "controller|operator|reconciler" + - "foregroundDeletion|backgroundDeletion" + - pass: > + "The controller validates that a finalizer was set by an authorized party + (e.g., only the controller itself or a known set of components) before + blocking deletion based on its presence. Finalizer removal requires + authentication as the original setter or an administrator. Stale finalizers + (orphaned when the original setter is gone) have a timeout or manual + override mechanism." + Rationale: "An attacker can add a finalizer to a resource, causing the + deletion to hang indefinitely (the resource enters Terminating state but + never completes). If the controller blindly respects all finalizers + without verifying the setter's identity, the attacker can create a + denial-of-service on resource cleanup." + - fail: > + "Controller does not verify the authority of the finalizer setter before + honoring it. An attacker can add a finalizer to a resource, blocking + deletion without authorization. Recommend implementing finalizer + provenance checks and a stale-finalizer timeout mechanism." +``` + +## Resolution Path +1. Validate all ownerReference fields (including uid) before acting on ownership +2. Reject cross-namespace ownerReferences explicitly +3. Implement finalizer provenance checking — only honor finalizers from known, authorized setters +4. Add a stale finalizer timeout or manual override for orphaned finalizers \ No newline at end of file diff --git a/skills/cloud/container-security/gates/workload-identity-token-audience-gate.md b/skills/cloud/container-security/gates/workload-identity-token-audience-gate.md new file mode 100644 index 00000000..c8ffd38c --- /dev/null +++ b/skills/cloud/container-security/gates/workload-identity-token-audience-gate.md @@ -0,0 +1,72 @@ +# Workload Identity Token Audience Scope Gate + +## Purpose +Prevents false-positive findings when projected service account tokens set explicit audience and short TTL, by requiring the reviewer to verify that the token audience is not accepted by unintended cloud APIs or internal services, and that tokens are not mounted into sidecar/debug containers that do not need them. + +## Detection Logic + +### Trigger Conditions +Fire this gate when ALL of the following are true: +1. Pod uses projected service account (Workload Identity) tokens with explicit audience +2. Token has short TTL configured +3. Token audience could match unintended cloud APIs or internal services, or token is mounted into a sidecar/debug container + +### Gate Check: Token Audience Scope Validation + +```yaml +check_token_audience_scope: + - detection_patterns: + - "projected service account|workload identity" + - "token audience|audience|--audience" + - "token expiration|expirationSeconds|TTL" + - "serviceAccountToken|token request" + - "gke-wi|iam\.gserviceaccount\.com" + - pass: > + "Each projected token's audience is scoped to the single intended API or + service. The audience does not match a broader pattern (e.g., + `https://iam.googleapis.com/` without a specific service resource). Token + TTL is set to the minimum viable duration (1 hour or less)." + Rationale: "A Workload Identity token with audience + `https://iam.googleapis.com/` (no resource) is accepted by all IAM + methods, effectively granting broader access than intended. The token's + audience must be as specific as the receiving service requires. A long + TTL increases the exposure window if the pod is compromised." + - fail: > + "Token audience is overly broad (e.g., `https://iam.googleapis.com/` + without resource, or a generic audience that matches multiple services). + TTL exceeds 1 hour without documented operational requirement. Recommend + narrowing the audience to the specific service/resource and reducing TTL." +``` + +### Gate Check: Token Mount Scope + +```yaml +check_token_mount_scope: + - detection_patterns: + - "serviceAccountToken|token mount" + - "sidecar|init container|debug container" + - "volumeMount|volume|projected" + - "serviceAccountName|service account" + - "containers:|spec.containers" + - pass: > + "Workload identity tokens are mounted only into the container(s) that + require them. Sidecar containers, init containers, and debug/ephemeral + containers do not receive the token unless they have a documented need. + Token mounts use read-only filesystem and least-privilege volume + projection." + Rationale: "A token mounted into a sidecar or debug container that does not + need it expands the attack surface. If the sidecar is compromised, the + token can be exfiltrated and used to authenticate to the unintended + service as the pod's identity." + - fail: > + "Workload identity token is mounted into containers (sidecar, init, + debug) that do not have a documented need for it. Recommend scoping token + mounts to only the containers that require authentication, and using + read-only mounts." +``` + +## Resolution Path +1. Scope each token audience to the single intended API/service, not a broad pattern +2. Set token TTL to minimum viable duration (1 hour or less) +3. Mount tokens only into containers with documented authorization requirements +4. Use read-only filesystem for token volumes \ No newline at end of file