From ccf5c12ec4db8c9cd889b745207ddf7d3e3c4af1 Mon Sep 17 00:00:00 2001 From: Isaac Schepp Date: Fri, 9 Oct 2026 07:41:51 -0500 Subject: [PATCH 1/2] fix: Bump Go toolchain to 1.27.2 for standard library vulnerabilities Resolves govulncheck alerts GO-2026-6599, 6600, 6603, 6604, 6605, 6607, 6608, 6609, 6610, 6611, 6612, 6613 and 6617, all in the standard library (net/http, html/template, os, crypto/tls, net/textproto) and fixed in go1.27.2. --- ci-tools/go.mod | 2 +- go.mod | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ci-tools/go.mod b/ci-tools/go.mod index c8439faf..cac8758e 100644 --- a/ci-tools/go.mod +++ b/ci-tools/go.mod @@ -2,7 +2,7 @@ module github.com/genealogix/glx/ci-tools go 1.27.0 -toolchain go1.27.1 +toolchain go1.27.2 tool ( github.com/hmarr/codeowners/cmd/codeowners diff --git a/go.mod b/go.mod index c70070a5..813150af 100644 --- a/go.mod +++ b/go.mod @@ -2,7 +2,7 @@ module github.com/genealogix/glx go 1.27.0 -toolchain go1.27.1 +toolchain go1.27.2 require ( github.com/brianvoe/gofakeit/v7 v7.17.1 From 78368ae457279019834a7170b2cecb6cdc392715 Mon Sep 17 00:00:00 2001 From: Isaac Schepp Date: Fri, 9 Oct 2026 08:00:11 -0500 Subject: [PATCH 2/2] fix: Build gosec and golangci-lint against x/tools that reads Go 1.27.2 export data Go 1.27.2 writes export data version 5. golangci-lint v2.13.2 and every gosec release up to v2.29.0 are built against golang.org/x/tools <= v0.49.0, which stops at version 4, so both type-checked nothing on this branch and failed ("export data version 5 is greater than maximum supported version 4"). - Bump .golangci-lint-version to v2.14.0 (x/tools v0.50.0), and replace the one new modernize finding it reports (strings.CutLast in driftcheck). - Build the pinned gosec in a throwaway module with x/tools raised to v0.50.0, in CI and in `make gosec`, until a gosec release carries it (securego/gosec#1771). The .gosec-version pin is unchanged. --- .github/workflows/security.yml | 17 ++++++++++++++++- .golangci-lint-version | 2 +- Makefile | 12 +++++++++++- ci-tools/README.md | 6 ++++++ tools/driftcheck/allowlist.go | 4 ++-- 5 files changed, 36 insertions(+), 5 deletions(-) diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml index 34438346..dd0b6f0a 100644 --- a/.github/workflows/security.yml +++ b/.github/workflows/security.yml @@ -128,10 +128,25 @@ jobs: # not a `go install ...@vX.Y.Z` line in a `run:` block. The weekly # gosec-pin-currency.yml workflow is what keeps the pin from rotting — # deliberately a separate workflow, see the header comment. + # + # TEMPORARY (securego/gosec#1771): every gosec release up to v2.29.0 is + # built against golang.org/x/tools <= v0.49.0, whose export-data reader + # stops at version 4. Go 1.27.2 writes version 5, so a plain install + # type-checks nothing ("export data version 5 is greater than maximum + # supported version 4") and exits 1. Until a gosec release carries + # x/tools >= v0.50.0, build the pinned gosec in a throwaway module with + # x/tools raised to v0.50.0, then return to the one-line + # `go install ...@${v}`. Keep GOSEC_XTOOLS in sync with the Makefile. + env: + GOSEC_XTOOLS: v0.50.0 run: | v="$(tr -d '[:space:]' < .gosec-version)" printf '%s' "$v" | grep -qE '^v[0-9]+\.[0-9]+\.[0-9]+$' || { echo "invalid .gosec-version: $v (expected vMAJOR.MINOR.PATCH)" >&2; exit 1; } - go install "github.com/securego/gosec/v2/cmd/gosec@${v}" + build="$(mktemp -d)" + cd "$build" + go mod init gosec-build + go get "github.com/securego/gosec/v2/cmd/gosec@${v}" "golang.org/x/tools@${GOSEC_XTOOLS}" + go install github.com/securego/gosec/v2/cmd/gosec - name: Run gosec # Staged write + guarded upload, adapted from govulncheck above diff --git a/.golangci-lint-version b/.golangci-lint-version index 095c2a17..d4174a4e 100644 --- a/.golangci-lint-version +++ b/.golangci-lint-version @@ -1 +1 @@ -v2.13.2 +v2.14.0 diff --git a/Makefile b/Makefile index 02d10f34..213c199e 100644 --- a/Makefile +++ b/Makefile @@ -142,10 +142,20 @@ ci-tools-tidy-check: ## Verify ci-tools/go.mod and ci-tools/go.sum are tidy vulncheck: ## Run govulncheck against the Go vulnerability DB (pinned via ci-tools/go.mod) go tool -modfile=ci-tools/go.mod govulncheck ./... +# TEMPORARY (securego/gosec#1771): gosec releases up to v2.29.0 cannot read Go +# 1.27.2's export data, so the pinned gosec is built in a throwaway module with +# golang.org/x/tools raised to GOSEC_XTOOLS. Keep it in sync with security.yml, and +# return to `go run ...@$$v` once a gosec release carries x/tools >= v0.50.0. +GOSEC_XTOOLS ?= v0.50.0 + gosec: ## Run gosec static security analysis (pinned via .gosec-version) @v="$$(tr -d '[:space:]' < .gosec-version)"; \ printf '%s' "$$v" | grep -qE '^v[0-9]+\.[0-9]+\.[0-9]+$$' || { echo "invalid .gosec-version: $$v (expected vMAJOR.MINOR.PATCH)" >&2; exit 1; }; \ - go run "github.com/securego/gosec/v2/cmd/gosec@$$v" -quiet ./... + build="$$(mktemp -d)"; trap 'rm -rf "$$build"' EXIT; \ + ( cd "$$build" && go mod init gosec-build >/dev/null 2>&1 && \ + go get "github.com/securego/gosec/v2/cmd/gosec@$$v" "golang.org/x/tools@$(GOSEC_XTOOLS)" >/dev/null 2>&1 && \ + GOOS="$$(go env GOHOSTOS)" GOARCH="$$(go env GOHOSTARCH)" go build -o "$$build/gosec" github.com/securego/gosec/v2/cmd/gosec ) || { echo "building gosec $$v failed" >&2; exit 1; }; \ + "$$build/gosec" -quiet ./... ## Licensing # go-licenses is intentionally NOT in ci-tools/go.mod — its tree pulls diff --git a/ci-tools/README.md b/ci-tools/README.md index cc6feb44..2707f5e5 100644 --- a/ci-tools/README.md +++ b/ci-tools/README.md @@ -42,6 +42,12 @@ inherited by anyone importing `github.com/genealogix/glx/go-glx` as a library. workflow rather than a job in `security.yml` on purpose — `security.yml` is the Code Scanning setup for gosec and govulncheck, and any failing job in it marks both tools as "reporting errors" on the tool status page (#1145). + **Temporarily** (securego/gosec#1771), CI and `make gosec` build the pinned + gosec in a throwaway module with `golang.org/x/tools` raised to `v0.50.0`: + gosec releases up to v2.29.0 cannot read the export data Go 1.27.2 writes. That + module's `go.mod` is never committed, so the tree above stays out of + `dependency-review`. Drop the override once a gosec release carries + `x/tools` >= v0.50.0. - **go-licenses** stays on a version-pinned `go install github.com/google/go-licenses/v2@v2.0.1` in `.github/workflows/license-compliance.yml` (and a matching `go run` in diff --git a/tools/driftcheck/allowlist.go b/tools/driftcheck/allowlist.go index 454c31f2..a57df69b 100644 --- a/tools/driftcheck/allowlist.go +++ b/tools/driftcheck/allowlist.go @@ -123,8 +123,8 @@ func symbolMatches(e *allowlistEntry, f *finding) bool { // splitSymbol divides "Type.Field" into ("Type", "Field"). A bare symbol // returns ("", symbol). func splitSymbol(symbol string) (owner, name string) { - if i := strings.LastIndex(symbol, "."); i >= 0 { - return symbol[:i], symbol[i+1:] + if before, after, found := strings.CutLast(symbol, "."); found { + return before, after } return "", symbol