From 540ed2fa54fc7b8fa7fc7d577a8f4830b04184c2 Mon Sep 17 00:00:00 2001 From: Don Petry <36422719+don-petry@users.noreply.github.com> Date: Wed, 4 Nov 2026 15:27:25 -0600 Subject: [PATCH 1/2] fix(dependency-audit): bump govulncheck to v1.9.0 so it runs on Go 1.27 govulncheck v1.1.4 vendors golang.org/x/tools v0.29.0, whose SSA builder panics (`unexpected expr: *ast.KeyValueExpr`) on Go 1.27, which setup-go's `stable` now installs. The Go audit then fails for every caller with a go.mod, e.g. combsmith/broodly ./apps/api. v1.9.0 (x/tools v0.52.0) runs clean on the same toolchain. Keep Go on `stable`: setup-go sets GOTOOLCHAIN=local, so a fixed Go pin would break the job when a caller's go.mod moves past it. Document that choice in the header and add a test that keeps the pin at v1.9.0 or later and in step with the header. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/dependency-audit-reusable.yml | 9 +++++++-- .../dependency-audit/dependency-audit.bats | 13 +++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dependency-audit-reusable.yml b/.github/workflows/dependency-audit-reusable.yml index 0e547b62a..df56b9248 100644 --- a/.github/workflows/dependency-audit-reusable.yml +++ b/.github/workflows/dependency-audit-reusable.yml @@ -13,11 +13,16 @@ # reusable's own commit and source it. # # Pinned tool versions (update deliberately): -# govulncheck v1.1.4 | cargo-audit 0.22.1 | pip-audit 2.9.0 +# govulncheck v1.9.0 | cargo-audit 0.22.1 | pip-audit 2.9.0 # Python 3.13 for pip-audit (`python-version` input). Never a floating "3.x": # a new Python release can break the hash-locked tooling for every caller at # once (3.15 removed sre_constants, crashing pip-api 0.0.34's vendored # pyparsing). +# Go `stable` for govulncheck, on purpose: setup-go sets GOTOOLCHAIN=local, so +# the toolchain must be at least every audited go.mod's `go` line, and a fixed +# pin would break the job the day a caller bumps it. The cost is that a new Go +# release can outrun an old govulncheck's x/tools parser (v1.1.4 panicked with +# `unexpected expr: *ast.KeyValueExpr` on Go 1.27), so keep govulncheck current. name: Dependency audit (Reusable) on: @@ -149,7 +154,7 @@ jobs: go-version: "stable" - name: Install govulncheck - run: go install golang.org/x/vuln/cmd/govulncheck@v1.1.4 # NOSONAR(githubactions:S8545) pinned @vX.Y.Z is reproducible (verified via Go checksum DB); no --locked equivalent + run: go install golang.org/x/vuln/cmd/govulncheck@v1.9.0 # NOSONAR(githubactions:S8545) pinned @vX.Y.Z is reproducible (verified via Go checksum DB); no --locked equivalent - name: Audit Go dependencies run: | diff --git a/test/workflows/dependency-audit/dependency-audit.bats b/test/workflows/dependency-audit/dependency-audit.bats index 384603a30..c5da97505 100644 --- a/test/workflows/dependency-audit/dependency-audit.bats +++ b/test/workflows/dependency-audit/dependency-audit.bats @@ -257,6 +257,19 @@ TOML [ "$(yq -r '.jobs.detect.name' "$DA_WORKFLOW")" = 'Detect ecosystems' ] } +# govulncheck runs on Go `stable`; v1.1.4's x/tools parser panicked on Go 1.27 +# (`unexpected expr: *ast.KeyValueExpr`), failing every Go audit. The pin must +# not fall back below v1.9.0 and must match the header's pinned-versions line. +@test "workflow: govulncheck is pinned at v1.9.0 or later, matching the header" { + local install pin header + install="$(yq -r '.jobs["audit-go"].steps[] | select(.name == "Install govulncheck") | .run' "$DA_WORKFLOW")" + pin="$(grep -oE 'govulncheck@v[0-9]+\.[0-9]+\.[0-9]+' <<<"$install" | cut -d@ -f2)" + header="$(grep -oE '^# govulncheck v[0-9]+\.[0-9]+\.[0-9]+' "$DA_WORKFLOW" | awk '{print $3}')" + [ -n "$pin" ] + [ "$pin" = "$header" ] + [ "$(printf '%s\n' v1.9.0 "$pin" | sort -V | head -1)" = 'v1.9.0' ] +} + @test "workflow: tooling is checked out from the reusable's own commit, outside the scanned tree" { local job for job in audit-cargo audit-pip audit-gate; do From a58e2172c8d087137109ecf118f09b15a8b0f21f Mon Sep 17 00:00:00 2001 From: Don Petry <36422719+don-petry@users.noreply.github.com> Date: Wed, 4 Nov 2026 15:35:08 -0600 Subject: [PATCH 2/2] test(dependency-audit): anchor the govulncheck pin check to the install command Match the whole step, comment stripped, against the one pinned `go install golang.org/x/vuln/cmd/govulncheck@vX.Y.Z`, so a version in a trailing comment or a pre-release suffix cannot satisfy the check. Co-Authored-By: Claude Opus 5.5 --- test/workflows/dependency-audit/dependency-audit.bats | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/workflows/dependency-audit/dependency-audit.bats b/test/workflows/dependency-audit/dependency-audit.bats index c5da97505..73a0501f7 100644 --- a/test/workflows/dependency-audit/dependency-audit.bats +++ b/test/workflows/dependency-audit/dependency-audit.bats @@ -263,7 +263,10 @@ TOML @test "workflow: govulncheck is pinned at v1.9.0 or later, matching the header" { local install pin header install="$(yq -r '.jobs["audit-go"].steps[] | select(.name == "Install govulncheck") | .run' "$DA_WORKFLOW")" - pin="$(grep -oE 'govulncheck@v[0-9]+\.[0-9]+\.[0-9]+' <<<"$install" | cut -d@ -f2)" + # The whole step, comment stripped, must be the one pinned install: a version + # in a trailing comment or a pre-release suffix must not satisfy the check. + pin="$(sed -E 's/[[:space:]]+#.*$//' <<<"$install" \ + | sed -nE 's|^go install golang\.org/x/vuln/cmd/govulncheck@(v[0-9]+\.[0-9]+\.[0-9]+)$|\1|p')" header="$(grep -oE '^# govulncheck v[0-9]+\.[0-9]+\.[0-9]+' "$DA_WORKFLOW" | awk '{print $3}')" [ -n "$pin" ] [ "$pin" = "$header" ]