feat(supply-chain): Track S quick wins — govulncheck + readonly + dependabot + detect-secrets#27
Open
remyluslosius wants to merge 1 commit into
Open
feat(supply-chain): Track S quick wins — govulncheck + readonly + dependabot + detect-secrets#27remyluslosius wants to merge 1 commit into
remyluslosius wants to merge 1 commit into
Conversation
Four parallel-safe Track S items + the toolchain bump that the
govulncheck gate immediately demands. Closes the worst of the
supply-chain governance gaps that the OpenWatch-team audit surfaced.
## Lands
### S-012 — Dependabot Go ecosystem (was missing entirely)
New .github/dependabot.yml with TWO ecosystem entries:
- gomod (weekly Monday, minor + patch grouped, max 10 open PRs)
- github-actions (weekly Monday, minor + patch grouped, max 5 open PRs)
The repo previously had NO dependabot config at all. The github-actions
half catches the Node.js 20 deprecation warnings we already see in CI
logs (actions/checkout@v4 + actions/setup-go@v5).
### S-005 — govulncheck merge gate (was not wired)
- Makefile: new `vuln` target reading go.mod's `go` directive to pin
GOTOOLCHAIN explicitly. Without that pin, `go run pkg@latest` picks
go1.25.x which can't typecheck go1.26+ source. The pin auto-tracks
future go.mod bumps.
- ci.yml: new Vulnerability Scan job calling `make vuln`. Blocks merge
on CALLED vulnerabilities (uncalled stdlib/dep vulns reported but
not failing).
The very first run of this gate found 6 stdlib CVEs (crypto/x509,
crypto/tls, net/http) called by kensa code. All resolved by the
go.mod toolchain bump 1.26.1 → 1.26.3 in this same commit — see
below.
### S-014 — read-only modules + tidy no-op drift gate (was not wired)
- ci.yml: top-level env adds GOFLAGS: '-mod=readonly' so any go step
that would mutate go.mod/go.sum fails loudly. A few jobs unset it
per-step where they legitimately need write access (the new
Vulnerability Scan, Module drift check, and the existing release
pipeline which needs `go mod tidy` from goreleaser's before-hooks).
- Makefile: new `mod-tidy-check` target. Saves pre-tidy state,
runs `go mod tidy`, diffs against saved state (NOT against HEAD —
comparing to HEAD would false-fail on intentional in-flight go.mod
edits during development). One-line fix message points contributor
at `go mod tidy`.
- ci.yml: new Module drift check job calling `make mod-tidy-check`.
### S-006 — detect-secrets baseline + CI scan (was partial)
- .secrets.baseline: initial scan captures 3 known-false-positive
findings:
- internal/evidence/signer.go:178 — "Secret Keyword" hit on the
error message string containing "private key"
- pkg/kensa/kensa_test.go:29 — test-fixture Ed25519 private key
(already excluded from the existing detect-private-key hook;
detect-secrets is a separate detector)
- specs/cli/password.spec.yaml:10 — the literal word "password"
in the cli-password-prompt spec's description
All three are confirmed not-actually-secrets.
- ci.yml: new Secret scan (detect-secrets) job runs the baseline scan
on every PR. Drift (new findings not in baseline) fails the job.
- .pre-commit-config.yaml: detect-secrets hook added alongside the
existing hooks. Default-stage so contributors see new findings
before they push.
### go.mod toolchain bump (govulncheck-driven)
go 1.26.1 → 1.26.3. Resolves the 6 stdlib CVEs the new govulncheck gate
found on its very first run:
GO-2026-4866 — case-sensitive excludedSubtrees in crypto/x509 (auth bypass)
GO-2026-4870 — unauthenticated TLS 1.3 KeyUpdate DoS in crypto/tls
GO-2026-4918 — infinite loop in HTTP/2 transport (golang.org/x/net)
GO-2026-4946 — inefficient policy validation in crypto/x509
GO-2026-4947 — unexpected work during chain building in crypto/x509
GO-2026-4971 — NUL byte panic in net.Dial on Windows
The bump itself is one line in go.mod; go's module system handles the
rest via the toolchain directive (the matching toolchain auto-downloads).
Post-bump govulncheck reports 0 called vulnerabilities.
## Local validation
go test ./... 69 packages green
make build && kensa version reports 0.2.1
gofmt -l . clean
make vuln 0 called vulnerabilities
make mod-tidy-check no-op (tidy is idempotent)
detect-secrets scan ... baseline stable
goreleaser check 1 config validated
## What this PR does NOT do (next on Track S)
- S-010 system-supply-chain.spec.yaml (Tier 1 foundation spec) — needs
proper SDD treatment in its own PR
- S-011 depguard with the 10-dep starting allowlist — gated on S-010
- S-013 SBOM (CycloneDX) on release tag — gated on S-001 (FIPS) for
release.yml ordering
- The FIPS chain (S-001..S-004)
## §7 failure-mode analysis
Touches CI configuration + go.mod toolchain directive — no engine /
handler / rollback code change.
1. **What could this do wrong in production?** The go.mod bump 1.26.1
→ 1.26.3 changes which Go stdlib code links into the binary. The
stdlib fixes in 1.26.3 are all security patches in crypto/x509,
crypto/tls, net/http, net — paths kensa uses through TLS handshake
and HTTP (PDF gen), x509 cert verification (agent framing). The
semantics of these APIs don't change in a patch release; only their
bug fixes do. Local tests + goreleaser snapshot pass post-bump.
2. **Rollback sufficient?** Not applicable — no engine state. Revert
commit if needed.
3. **Edge case NOT safe for?** A CI environment without Go 1.26.3
toolchain available would fail to fetch it. GitHub Actions runners
reliably have all recent Go versions; air-gapped CI mirrors might
need a manual cache update.
## SDD
No new specs — these are CI/config additions, not behaviour changes.
S-010 will land the proper supply-chain spec as a follow-up PR.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Lands the four parallel-safe Track S items (S-005 / S-006 / S-012 / S-014) plus the go.mod toolchain bump 1.26.1 → 1.26.3 that the new govulncheck gate immediately demanded on first run.
Closes the worst of the supply-chain governance gaps surfaced by the OpenWatch-team parity audit (2026-05-29): the repo had no
.github/dependabot.ymlat all, nogovulncheckwiring, no-mod=readonlyenforcement, nogo mod tidydrift check, and nodetect-secretsCI gate.Four quick wins + one CVE fix
S-012 —
.github/dependabot.yml(new — was missing entirely)Two ecosystem entries (gomod + github-actions), weekly Monday cadence, minor+patch grouped per dep, max 10 PRs (gomod) / 5 PRs (github-actions). The github-actions half catches the Node.js 20 deprecation warnings we already see in CI logs.
S-005 —
govulncheckmerge gate (new)make vulntarget reads go.mod'sgodirective to pinGOTOOLCHAINexplicitly (otherwisego run pkg@latestpicks go1.25.x which can't typecheck go1.26+ source). Auto-tracks future go.mod bumps.Vulnerability ScanCI job callsmake vuln. Blocks merge on CALLED vulnerabilities (uncalled stdlib/dep vulns reported but not failing).First run of this gate found 6 stdlib CVEs called by kensa code. All resolved by the go.mod toolchain bump in this same PR (see below).
S-014 —
-mod=readonly+go mod tidyno-op gate (new)GOFLAGS: '-mod=readonly'inci.yml— any go step that would mutate go.mod/go.sum fails loudly. Three jobs (Vulnerability Scan, Module drift check, Release pipeline) unset it per-step where they legitimately need write access.make mod-tidy-checktarget. Saves pre-tidy state → runs tidy → diffs against saved state (NOT against HEAD — would false-fail on intentional in-flight go.mod edits during development). Clear one-line fix message points contributor atgo mod tidy.Module drift checkCI job callsmake mod-tidy-check.S-006 — detect-secrets baseline + CI scan (new)
.secrets.baselineinitial scan captures 3 confirmed false-positive findings:internal/evidence/signer.go:178— "Secret Keyword" hit on the error message containing "private key"pkg/kensa/kensa_test.go:29— test-fixture Ed25519 private key (existingdetect-private-keyexclude already covers this; detect-secrets is a separate detector)specs/cli/password.spec.yaml:10— the literal word "password" in the cli-password-prompt specSecret scan (detect-secrets)CI job runs the baseline scan on every PR; drift (new findings not in baseline) fails the job..pre-commit-config.yamlgains the detect-secrets hook alongside existing hooks, default-stage so contributors see findings before pushing.go.mod toolchain bump 1.26.1 → 1.26.3 (CVE-driven)
Resolves the 6 stdlib CVEs the new govulncheck gate found:
Bump is one line in go.mod; Go's module system handles the rest via the toolchain directive (matching toolchain auto-downloads). Post-bump
make vulnreports 0 called vulnerabilities.Local validation
go test ./...make build && kensa versiongofmt -l .make vulnmake mod-tidy-checkdetect-secrets scan --baseline ...goreleaser checkWhat this PR does NOT do (next on Track S)
system-supply-chain.spec.yaml(Tier 1 foundation spec). Needs proper SDD treatment in its own PR.§7 failure-mode analysis
Touches CI configuration + go.mod toolchain directive — no engine / handler / rollback code change.
🤖 Generated with Claude Code