ci: pin govulncheck, narrow release permissions#436
Conversation
|
✅ OpenCodeReview: No comments generated. Looks good to me. |
|
Thanks for the thorough analysis and detailed PR description. Changes 1 & 2 (pin govulncheck + narrow permissions) look good — the govulncheck pin addresses a real stability issue (cf. For change 3 (SHA-pin action-gh-release): could you drop this one? The maintenance overhead (manual SHA lookups on every bump, less readable diffs) outweighs the security benefit here — the job already has scoped permissions limiting blast radius, and it conflicts with the pending dependabot PR #347. Happy to merge the other two as-is. |
Pin govulncheck to v1.6.0 instead of @latest. The argument is reproducibility, not supply chain: golang.org/x/vuln is the Go team's own module and go install is already checksum-verified via GOSUMDB. What @latest costs is a new govulncheck release turning CI red on an unchanged tree. This gate is load-bearing - e6e5da0 bumped the Go image to fix GO-2026-5856 after govulncheck caught it - so protecting it from unrelated churn is worth a pin. Pinning costs nothing in scan freshness: the vulnerability database is fetched at runtime, independently of the binary version. Verified: Scanner govulncheck@v1.6.0, DB updated 2026-07-08, no vulnerabilities, exit 0. Narrow release.yml's workflow-level permissions from contents: write to contents: read. Only the build job inherits it, and it only checks out and uploads artifacts - upload-artifact authenticates with ACTIONS_RUNTIME_TOKEN, not GITHUB_TOKEN. The release and npm-publish jobs declare their own job-level permissions, which replace the inherited set entirely, so both are unaffected. Verified with actionlint (clean across all workflows) and by confirming the release.yml still parses as YAML.
1510512 to
4c0af22
Compare
|
Dropped change 3. Force-pushed actionlint is clean and the two remaining hunks are unchanged. Ready when you are. |
Description
Two independent hardening changes to the CI/release workflows, two lines total.
The second is the project's own documented review rule rather than my preference.
internal/config/rules/rule_docs/github_workflows.md:4says each job "should declare only thepermissions it needs". This PR applies that to the repo's own release workflow.
1. Pin
govulncheck— for reproducibility, not supply chainci.yml:33runsgo install golang.org/x/vuln/cmd/govulncheck@latest, so a new govulncheckrelease can turn CI red on an unchanged tree. The gate is real:
e6e5da0("ci: bump Go image to1.26.5 to fix GO-2026-5856 govulncheck failure") is a stdlib vulnerability it caught. The
vulnerability database is fetched at runtime, independently of the binary version, so pinning
does not stale the scan — a pinned v1.6.0 binary reported
DB updated: 2026-07-08,No vulnerabilities found., exit 0.2. Narrow
release.ymlworkflow-level permissionsrelease.yml:7-8grants workflow-levelcontents: write. Only one job actually inherits it, andthat job never writes. Traced all three:
permissions:build(:11)upload-artifact@v4authenticates withACTIONS_RUNTIME_TOKEN, notGITHUB_TOKENrelease(:58):61-64contents: write,id-token: write,attestations: writenpm-publish(:159):164-165contents: readsecrets.NPM_TOKENJob-level
permissions:replaces the inherited set entirely, soreleaseandnpm-publishare already fully insulated today. Narrowing is a strict no-op for them, and drops an unused
write grant from
build, whose lines 11-57 contain onlyactions/checkout@v4andactions/upload-artifact@v4— noGITHUB_TOKEN, nogh.Verification
actionlintv1.7.12 exit 0 across all four workflows, andyaml.safe_loadon both changedfiles. The permission matrix above was asserted from the parsed YAML after the edit, not eyeballed.
Limitations
release.ymlonly fires onpush: tags: ['v*'], so the permission narrowing cannot be proven bythis PR's checks — the first real exercise is the next release, and the evidence is the traced
matrix above. If
buildever gains a step that writes viaGITHUB_TOKENit will need its ownjob-level block. Dependabot's
github-actionsecosystem does not covergo installlines, sobumping the govulncheck pin stays manual.
Type of Change
How Has This Been Tested?
govulncheck@v1.6.0, confirmedScanner: govulncheck@v1.6.0, a runtime-fetchedDB updated: 2026-07-08, andNo vulnerabilities found.with exit 0buildcontains noGITHUB_TOKENorghusageactionlintv1.7.12 — exit 0Checklist
AI assistance: Claude Code helped research and verify this change. I reviewed the full diff
and take responsibility for it.