diff --git a/skills/devsecops/pipeline-security/SKILL.md b/skills/devsecops/pipeline-security/SKILL.md index 66de2470..fc49f38f 100644 --- a/skills/devsecops/pipeline-security/SKILL.md +++ b/skills/devsecops/pipeline-security/SKILL.md @@ -139,6 +139,23 @@ Read each pipeline configuration file and evaluate against SLSA v1.0 build track - [ ] Provenance is non-falsifiable (generated by the build platform, not user-defined steps). - [ ] No use of self-hosted runners in security-critical build paths (unless hardened and ephemeral). +#### Self-Hosted Runner Trust-Boundary Evidence Gates + +Do not classify every self-hosted runner as equally risky. Preserve the evidence that distinguishes a hardened runner pool from a persistent shared execution environment: + +| Evidence Item | Safe Signal | Finding When Missing | +|---|---|---| +| Runner lifetime | Ephemeral runner destroyed after one job, or clean VM/container image recreated per job | Persistent workspace can carry files, credentials, or tooling between builds | +| Trust-boundary labels | Separate runner groups/labels for protected branches, releases, forks, and internal-only jobs | Untrusted PR code can share infrastructure with privileged release jobs | +| Workspace cleanup | Verified cleanup of workspace, temp directories, tool caches, Docker layers, and service containers | Prior job artifacts can poison later builds | +| Cache boundaries | Cache keys include trusted source, lockfile digest, architecture, and branch trust level | Fork or feature-branch cache can influence protected builds | +| Secret exposure | No long-lived secrets on runner disk; secrets injected only at job runtime and redacted from logs | Compromised job can persist credentials for later jobs | +| Network egress | Runner egress restricted to required registries/services; metadata endpoints protected | Build steps can exfiltrate secrets or reach internal services | +| Approval gates | Jobs using privileged runners require protected branch, environment, or maintainer approval | Unreviewed code can execute on high-trust runners | +| Runner updates | Runner agent and base image patch level are tracked and rotated | Outdated runner can become a durable foothold | + +If a self-hosted runner has all required isolation, cleanup, secret, and approval evidence, record it as a controlled exception rather than a default High finding. If a pipeline mixes fork PRs, untrusted branches, release signing, deployment secrets, or package publishing on the same persistent runner pool, report the trust-boundary violation explicitly. + **Determination logic:** The repository achieves the highest level for which ALL checklist items are satisfied. Partial compliance at a given level means the repository remains at the level below. --- @@ -277,6 +294,9 @@ on: pull_request_target - Secrets available to all workflows rather than scoped to specific environments. - No conditional checks on branch or environment before accessing sensitive resources. - Self-hosted runners shared across repositories with different trust levels. +- Self-hosted runners that allow fork PRs or untrusted branch builds to run before maintainer approval. +- Persistent workspaces, Docker volumes, tool caches, or package caches shared between untrusted and trusted jobs. +- Runner labels such as `self-hosted`, `linux`, or `prod` used too broadly to prove a trust boundary. **Grep patterns:** @@ -292,7 +312,7 @@ if: github.ref == 'refs/heads/main' runs-on: self-hosted # Shared runners are a risk ``` -**Finding format:** Report whether secrets and deployment capabilities are scoped to appropriate environments and branches, and whether runner infrastructure is properly segmented. +**Finding format:** Report whether secrets and deployment capabilities are scoped to appropriate environments and branches, whether runner infrastructure is segmented by trust level, and whether persistent workspaces/caches can bridge untrusted and privileged jobs. --- @@ -340,6 +360,8 @@ runs-on: self-hosted # Shared runners are a risk - Insecure runner images or outdated runner versions. - Missing network controls on build infrastructure. - Docker-in-Docker without appropriate security boundaries. +- Cleanup implemented only as a best-effort shell step that can be skipped after job cancellation or runner crash. +- Service containers or sibling Docker networks left running across jobs on a persistent runner. **Grep patterns:** @@ -353,7 +375,7 @@ ACTIONS_STEP_DEBUG: true docker.sock ``` -**Finding format:** Report runner configuration security, debug settings, and any privileged operations in the build environment. +**Finding format:** Report runner configuration security, debug settings, privileged operations, cleanup guarantees, and whether any persistent runner state can influence later jobs. ---