fix(validate-go): route govulncheck through the SHA-pinned fork for all repos#278
fix(validate-go): route govulncheck through the SHA-pinned fork for all repos#278devantler wants to merge 1 commit into
Conversation
…ll repos The upstream golang/govulncheck-action's composite action.yml tag-pins its own actions/checkout@v4.1.1 and actions/setup-go@v5.0.0. GitHub resolves the actions of every `uses:` in a job regardless of its `if:`, so merely *referencing* the upstream action in the no-allowlist branch failed the whole Vulnerability Scan job at workflow-prep time on any consumer that enforces a "pin every action to a full-length commit SHA" ruleset (e.g. ksail) — wedging that consumer's entire Go PR lane before any scan ran. Route all repos through the devantler/govulncheck-action fork (which SHA-pins its sub-actions). Behaviour is unchanged: with no .govulncheck-allow.txt the allow-file input is empty and the fork runs strict (byte-equivalent to upstream); an allowlist file takes the JSON-mode risk-acceptance path. Collapses the two if-gated scan steps into one. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR updates the reusable Validate Go Project workflow to ensure the govulncheck vulnerability scan works in repositories that enforce “pin every action to a full-length commit SHA” rulesets by removing all references to the upstream golang/govulncheck-action and routing all consumers through the SHA-pinned devantler/govulncheck-action fork.
Changes:
- Collapses the dual govulncheck steps (upstream vs fork) into a single fork-based step, with conditional allowlist behavior via the
allow-fileinput. - Updates workflow inline documentation to explain why the upstream action cannot be referenced (transitive tag-pins + workflow-prep resolution).
- Updates the README feature description to match the new “always fork” approach and rationale.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
README.md |
Updates Validate Go Project documentation to reflect using the SHA-pinned fork for govulncheck in all repos. |
.github/workflows/validate-go-project.yaml |
Removes upstream govulncheck action reference and uses the fork unconditionally, with conditional allowlist selection. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| repo-checkout: false | ||
| go-version-file: go.mod | ||
| allow-file: .govulncheck-allow.txt | ||
| # Empty ⇒ strict (fail on any reachable advisory, like the upstream action); | ||
| # set ⇒ JSON-mode allowlist that risk-accepts only the listed advisory IDs. | ||
| allow-file: ${{ steps.govulncheck-allow.outputs.present == 'true' && '.govulncheck-allow.txt' || '' }} |
Superseded by #279, which carries the identical fix (route govulncheck through the SHA-pinned |
Problem — the
validate-go-projectVulnerability Scan wedges SHA-pin-enforcing consumersksail's entire Go PR lane (#4986, dependabot #4945/#4905, and every future Go PR) has been failing the required 🛡️ Vulnerability Scan check. The failure is not a govulncheck finding — the job dies at workflow-prep:
Root cause: the upstream
golang/govulncheck-action@v1.0.4composite tag-pins its ownactions/checkout@v4.1.1andactions/setup-go@v5.0.0. GitHub resolves the actions of everyuses:in a job regardless of itsif:, so the current dual-path design (official action on the no-allowlist branch, fork on the allowlist branch) resolves both — and the upstream action's transitive tag refs are rejected at prep time by any consumer that enforces a "pin every action to a full-length commit SHA" repository ruleset (ksail does). The job never starts; the lane wedges.mainstays green because govulncheck ispull_request-only, hiding it from the default-branch view.This is a regression introduced when we adopted the upstream action (the previous in-house JSON-mode scan had no nested-action dependency).
Fix
Route all repos through the thin
devantler/govulncheck-actionfork (@feat/allow-file), which SHA-pins its sub-actions (actions/checkout@…v6.0.2,actions/setup-go@…v6.2.0). The upstream action is no longer referenced anywhere in the job, so no tag-pinned transitive deps reach the consumer's ruleset.Behaviour is unchanged — the fork is a strict superset of upstream:
.govulncheck-allow.txt→allow-fileinput is empty → fork runsgovulncheckstrict, byte-equivalent to the upstream action (any reachable advisory fails)..govulncheck-allow.txtpresent → JSON-mode allowlist that risk-accepts only the listed advisory IDs (the existing opt-in path, unchanged).Collapses the two
if-gated scan steps into one (the fork branches internally onallow-file). Net −23/+23 across the workflow + a README line.Trade-off to weigh (⚠️ reverses part of #276's design)
#276 deliberately kept the upstream action for no-allowlist repos to minimise the fork's blast radius. That goal is now in direct conflict with the org's own SHA-pinned-actions security policy: as shown above, the upstream action is fundamentally incompatible with that ruleset, even on the unused branch. Routing everyone through the fork widens the fork's blast radius but is required for SHA-pin consumers and is strictly more secure (SHA-pinned sub-actions). The escape hatch is documented inline: swap back to
golang/govulncheck-actiononce it ships theallow-filefeature and SHA-pins its sub-actions.Validation
actionlintclean (only the pre-existingcode-quality-scope false-positive, unrelated).action.yml: emptyallow-file⇒govulncheck -format text ./...(same as upstream); non-empty ⇒ JSON-mode allowlist.validate-go-project.yaml@v5.4.x) needs a ref bump to the new release to pick this up — its Go PR lane then unwedges.Draft for your promotion — the trade-off above is your call.