diff --git a/RUNBOOK.md b/RUNBOOK.md index 2b2a40d..d25f8e8 100644 --- a/RUNBOOK.md +++ b/RUNBOOK.md @@ -78,7 +78,26 @@ type=gha` are both no-ops. | The pipeline retriggers itself forever | The `bump` job commits to the repo it is triggered by. | `[skip ci]` in the commit message (Gitea honours it), **and** a `git diff --quiet` guard so an unchanged digest commits nothing. | | Service container unreachable at `localhost` | Jobs run *inside* a container, so a service is reached by its **service name**, not localhost. | `postgres:5432`, not `localhost:5432`. | -### 4. Verify the whole loop, not just the green checkmarks +### 4. Keeping trivy green + +The image gate is a moving target: trivy's vulnerability DB updates daily, so an image that +passed yesterday fails today without a single line of code changing. Two rules keep it sane. + +**Bump the version, do not add an ignore.** The worker image went 39 findings (2 CRITICAL) +→ 18 → 5 → 0 across three fixes, each a version bump or a removal: + +| Change | Result | +|---|---| +| `alpine/helm` 3.16.2 → 3.21.3, `kubectl` 1.31.2 → 1.35.3 | 39 → 18, both CRITICALs cleared | +| `kubectl` 1.35.3 → 1.36.2 (k8s 1.35.x vendors spdystream 0.5.0; the fix is 0.5.1) | 18 → 5 | +| dropped kubectl entirely — `helm --create-namespace` replaced `kubectl apply` | **5 → 0** | + +**The cheapest CVE is the binary you do not ship.** The last five findings lived in +kubectl's vendored `golang.org/x/net` and Go stdlib, inside the newest kubectl that exists — +no version cleared them. kubectl was in that image for exactly one call, and helm already +does the same thing with a flag. Removing it removed the CVEs, a binary, and an adapter. + +### 5. Verify the whole loop, not just the green checkmarks ```bash # the digest CI pushed