Skip to content

fix(deps): toolchain go1.26.5 + x/net v0.57.0 — clear 6 reachable vulns; govulncheck CI gate#278

Merged
saadqbal merged 2 commits into
developfrom
fix/276-toolchain-xnet-govulncheck
Jul 14, 2026
Merged

fix(deps): toolchain go1.26.5 + x/net v0.57.0 — clear 6 reachable vulns; govulncheck CI gate#278
saadqbal merged 2 commits into
developfrom
fix/276-toolchain-xnet-govulncheck

Conversation

@LukasWodka

@LukasWodka LukasWodka commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Summary

Security fix for the customer-installed CLI binary (WS-A.1 of epic tracebloc/backend#1106). Three changes:

  1. Toolchain pintoolchain go1.26.5 added to go.mod (latest 1.26.x patch, verified live against go.dev/dl at implementation time). go.mod previously had only go 1.26.0, so released binaries carried whichever stdlib the build runner resolved — including the four vulnerable stdlib packages below.
  2. x/net bumpgolang.org/x/net v0.49.0 → v0.57.0 (latest stable; the fix floor from the OSV entries is v0.55.0). Only x/net and its sibling x/{sys,term,text} modules move in go.sum — no k8s.io drift (verified by diff inspection).
  3. govulncheck CI gate — pinned govulncheck@v1.1.4 as a blocking job in build.yml (every PR + push to develop/main), plus a new vulncheck.yml with a weekly cron (Mon 05:30 UTC, checkout pinned to develop) + workflow_dispatch, so a CVE published against code we already ship reddens develop within a week. Matching pinned make vulncheck target wired into make ci.

Type

Security / tech-debt (dependency + toolchain bump, CI gate — no behavior change).

Before → after (govulncheck ./..., scanner v1.1.4, DB 2026-07-08)

Before (origin/develop @ 5af9a80): 6 reachable vulnerabilities

ID Package Found in Fixed in Example reachable path
GO-2026-5856 crypto/tls go1.26.3 go1.26.5 api.userAgentTransport.RoundTriptls.Conn.HandshakeContext; also submit.HTTPSubmitter.Submit, push.HasBOM, push.Stage
GO-2026-5039 net/textproto go1.26.3 go1.26.4 push.CheckCSVEncodingtextproto.Reader.ReadMIMEHeader
GO-2026-5038 mime go1.26.3 go1.26.4 submit.streamPodLogsAndParsemime.WordDecoder.DecodeHeader
GO-2026-5037 crypto/x509 go1.26.3 go1.26.4 push.HasBOMx509.Certificate.Verify; doctor.checkNodeFit
GO-2026-5026 golang.org/x/net/idna v0.49.0 v0.55.0 api.userAgentTransport.RoundTripidna.ToASCII
GO-2026-4918 x/net (HTTP/2) v0.49.0 v0.53.0 api.userAgentTransport.RoundTriphttp2.Transport.RoundTrip (infinite loop on bad SETTINGS_MAX_FRAME_SIZE)

The baseline scan matched the ticket exactly: 6 reachable (4 stdlib + 2 x/net at v0.49.0), reachable via api.userAgentTransport.RoundTrip, submit.HTTPSubmitter.Submit, push.CheckCSVEncoding.

After (this branch):

No vulnerabilities found.

release.yml / setup-go verification

  • release.yml, build.yml, and e2e.yml all use actions/setup-go@v5 with go-version-file: go.modno hardcoded Go version anywhere, so no workflow line needed fixing.
  • Caveat verified against the live actions/setup-go@v5 source: v5's parseGoVersionFile reads only the go directive (installs go1.26.0), not the toolchain directive (v6 added that). Correctness still holds: setup-go v5 never sets GOTOOLCHAIN, the repo sets it nowhere (grepped workflows/Makefile/scripts), and Go ≥1.21 defaults to GOTOOLCHAIN=auto — so go build in every job auto-switches to go1.26.5 per the new directive. Release binaries get the patched stdlib. (Confirmed locally: host Go is 1.26.3, yet go version inside the module reports go1.26.5.) A later setup-go v5→v6 bump would merely skip the ~70MB toolchain re-download per job — perf nit, left out to keep this PR minimal.
  • Weekly cron caveat: scheduled workflows fire from the default branch (main), so the cron activates once vulncheck.yml rides the normal develop → main promotion. Its checkout pins ref: develop, which is the branch the sweep should redden.
  • Making the new build.yml govulncheck job a required status check is a branch-protection setting — admin handoff for @LukasWodka after merge.

Test plan (everything below ran locally on this branch)

  • govulncheck ./... before: 6 reachable findings (full list above) — after: clean (also re-verified via make vulncheck)
  • go build ./... and go vet ./... under the pinned toolchain (go1.26.5)
  • go test -race -cover ./... — full unit suite green, ~49s, coverage unchanged (e.g. api 96.3%, submit 80.4%, push 89.0%)
  • make lint (pinned errcheck/ineffassign/misspell) + make fmt-check — green
  • Both workflow files YAML-parse; go.mod/go.sum diff inspected — only x/net + x/{sys,term,text} moved
  • Not run locally: the 8-platform build matrix, installer harness, schema-drift check, e2e/kind — CI covers these on this PR
  • .golangci.yml's go: "1.26" tracks the unchanged go 1.26.0 directive — no update needed

Release handoff

Cut v0.8.1 via the normal develop → main promotion after merge — rebuild + dep bump, no behavior change; flagging priority per epic tracebloc/backend#1106 (customers are installing v0.8.0 binaries with the six vulns above). @saadqbal

Fixes #276

🤖 Generated with Claude Code


Note

Medium Risk
Security-focused toolchain and dependency bumps for a customer-installed binary; no application logic changes, but release builds and CI now depend on the vuln DB and pinned Go patch.

Overview
Clears six reachable CVEs in the shipped CLI by pinning toolchain go1.26.5 (stdlib fixes) and bumping golang.org/x/net to v0.57.0 with aligned x/sys, x/term, and x/text bumps—no k8s.io module changes.

Adds blocking govulncheck@v1.1.4 on every PR/push in build.yml, a weekly vulncheck.yml sweep of develop (plus workflow_dispatch), and a matching make vulncheck step in make ci so local runs mirror CI.

Reviewed by Cursor Bugbot for commit 2b80082. Bugbot is set up for automated code reviews on this repo. Configure here.

LukasWodka and others added 2 commits July 14, 2026 14:08
govulncheck reported 6 reachable vulnerabilities in the shipped CLI:
4 stdlib (GO-2026-5856 crypto/tls, fixed go1.26.5; GO-2026-5039
net/textproto, GO-2026-5038 mime, GO-2026-5037 crypto/x509, all fixed
go1.26.4) plus 2 in golang.org/x/net v0.49.0 (GO-2026-4918 HTTP/2
infinite loop, fixed v0.53.0; GO-2026-5026 idna, fixed v0.55.0) —
reachable via api.userAgentTransport.RoundTrip,
submit.HTTPSubmitter.Submit, and push.CheckCSVEncoding among others.

go.mod had no toolchain directive, so v0.8.0 release binaries carried
whatever stdlib the runner's Go resolved to. Pin toolchain go1.26.5
(latest 1.26.x patch, verified against go.dev/dl) and bump x/net to
v0.57.0 (latest stable; fix floor was v0.55.0). Only x/net and its
sibling x/{sys,term,text} modules move — no k8s.io drift.

After: govulncheck ./... is clean; build, vet, -race suite, and lint
all green under the pinned toolchain.

Part of tracebloc/backend#1106 (WS-A). See #276.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Two copies of one pinned job (govulncheck@v1.1.4, setup-go with
go-version-file: go.mod so the module toolchain governs):

- build.yml: blocking job on every PR and push to develop/main —
  stops new code from introducing a reachable vuln.
- vulncheck.yml (new): weekly cron (Mon 05:30 UTC) + workflow_dispatch,
  checkout pinned to develop — a CVE published against code we already
  ship reddens develop within a week instead of waiting for the next
  PR. Cron activates once this file rides the normal develop -> main
  promotion (scheduled workflows fire from the default branch only).

Makefile grows a matching pinned `vulncheck` target, wired into
`make ci` to keep the "make ci green => CI green" invariant.

Part of tracebloc/backend#1106 (WS-A). See #276.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@LukasWodka

Copy link
Copy Markdown
Contributor Author

👋 Heads-up — Code review queue is at 38 / 30

Above the WIP limit. The team convention is to review existing PRs before opening new work.

Open PRs currently in Code review (oldest first):

Pull from review before opening new work. (This is a nudge from the kanban WIP check, not a block.)

@LukasWodka

Copy link
Copy Markdown
Contributor Author

@BugBot run

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 2b80082. Configure here.

@saadqbal
saadqbal merged commit 3fa6022 into develop Jul 14, 2026
23 checks passed
@saadqbal
saadqbal deleted the fix/276-toolchain-xnet-govulncheck branch July 14, 2026 12:45
@LukasWodka LukasWodka self-assigned this Jul 14, 2026
LukasWodka added a commit that referenced this pull request Jul 14, 2026
…findings

Pinned staticcheck@2025.1.1 joins the standalone lint set in both the
Makefile lint target and build.yml's lint job (-checks all,-ST1005),
mirroring the errcheck/ineffassign pin pattern. The golangci-lint OOM
story that originally disabled it is stale for the standalone binary:
a full run is ~12s wall locally.

Findings fixed (the full non-ST1005 set):
- ST1008: runSet (resources_set_test) returns (string, error), error last
- ST1003: CheckMaskIdColumn -> CheckMaskIDColumn (+ call sites/comments)
- ST1003: errors_as -> errorsAs, io_eof_or_similar -> ioEOFOrSimilar
- ST1020: CoreFloorText doc comment starts with the function name

ST1005 stays excluded: it flags ~58 customer-visible error strings that
need a wording review, not a mechanical sweep — separate follow-up.

Rebased onto develop: union-merged the lint job with develop's govulncheck
job (#278), coverage-floor step (#301) and deadcode advisory gate; kept the
audit comment #286 added above CheckMaskID*Column. The 'going back to the
action' comment in build.yml is KEPT (not deleted) — #6 is still open on
develop, so golangci-lint-action stays disabled and that rationale still
holds. Detached the four data_ingest_*.go header comments from the package
clause (#303 split) so the newly-enabled staticcheck gate is ST1000-clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
LukasWodka added a commit that referenced this pull request Jul 14, 2026
…findings

Pinned staticcheck@2025.1.1 joins the standalone lint set in both the
Makefile lint target and build.yml's lint job (-checks all,-ST1005),
mirroring the errcheck/ineffassign pin pattern. The golangci-lint OOM
story that originally disabled it is stale for the standalone binary:
a full run is ~12s wall locally.

Findings fixed (the full non-ST1005 set):
- ST1008: runSet (resources_set_test) returns (string, error), error last
- ST1003: CheckMaskIdColumn -> CheckMaskIDColumn (+ call sites/comments)
- ST1003: errors_as -> errorsAs, io_eof_or_similar -> ioEOFOrSimilar
- ST1020: CoreFloorText doc comment starts with the function name

ST1005 stays excluded: it flags ~58 customer-visible error strings that
need a wording review, not a mechanical sweep — separate follow-up.

Rebased onto develop: union-merged the lint job with develop's govulncheck
job (#278), coverage-floor step (#301) and deadcode advisory gate; kept the
audit comment #286 added above CheckMaskID*Column. The 'going back to the
action' comment in build.yml is KEPT (not deleted) — #6 is still open on
develop, so golangci-lint-action stays disabled and that rationale still
holds. Detached the four data_ingest_*.go header comments (#303 split) plus
exitcodes.go's (#284, which develop merged after this branch was cut) from
the package clause so the newly-enabled staticcheck gate is ST1000-clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
LukasWodka added a commit that referenced this pull request Jul 14, 2026
…findings

Pinned staticcheck@2025.1.1 joins the standalone lint set in both the
Makefile lint target and build.yml's lint job (-checks all,-ST1005),
mirroring the errcheck/ineffassign pin pattern. The golangci-lint OOM
story that originally disabled it is stale for the standalone binary:
a full run is ~12s wall locally.

Findings fixed (the full non-ST1005 set):
- ST1008: runSet (resources_set_test) returns (string, error), error last
- ST1003: CheckMaskIdColumn -> CheckMaskIDColumn (+ call sites/comments)
- ST1003: errors_as -> errorsAs, io_eof_or_similar -> ioEOFOrSimilar
- ST1020: CoreFloorText doc comment starts with the function name

ST1005 stays excluded: it flags ~58 customer-visible error strings that
need a wording review, not a mechanical sweep — separate follow-up.

Rebased onto develop: union-merged the lint job with develop's govulncheck
job (#278), coverage-floor step (#301) and deadcode advisory gate; kept the
audit comment #286 added above CheckMaskID*Column. The 'going back to the
action' comment in build.yml is KEPT (not deleted) — #6 is still open on
develop, so golangci-lint-action stays disabled and that rationale still
holds. Detached the four data_ingest_*.go header comments (#303 split) plus
exitcodes.go's (#284, which develop merged after this branch was cut) from
the package clause so the newly-enabled staticcheck gate is ST1000-clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
LukasWodka added a commit that referenced this pull request Jul 14, 2026
…findings (#302)

* ci: re-enable staticcheck (pinned standalone) + fix the 5 non-ST1005 findings

Pinned staticcheck@2025.1.1 joins the standalone lint set in both the
Makefile lint target and build.yml's lint job (-checks all,-ST1005),
mirroring the errcheck/ineffassign pin pattern. The golangci-lint OOM
story that originally disabled it is stale for the standalone binary:
a full run is ~12s wall locally.

Findings fixed (the full non-ST1005 set):
- ST1008: runSet (resources_set_test) returns (string, error), error last
- ST1003: CheckMaskIdColumn -> CheckMaskIDColumn (+ call sites/comments)
- ST1003: errors_as -> errorsAs, io_eof_or_similar -> ioEOFOrSimilar
- ST1020: CoreFloorText doc comment starts with the function name

ST1005 stays excluded: it flags ~58 customer-visible error strings that
need a wording review, not a mechanical sweep — separate follow-up.

Rebased onto develop: union-merged the lint job with develop's govulncheck
job (#278), coverage-floor step (#301) and deadcode advisory gate; kept the
audit comment #286 added above CheckMaskID*Column. The 'going back to the
action' comment in build.yml is KEPT (not deleted) — #6 is still open on
develop, so golangci-lint-action stays disabled and that rationale still
holds. Detached the four data_ingest_*.go header comments (#303 split) plus
exitcodes.go's (#284, which develop merged after this branch was cut) from
the package clause so the newly-enabled staticcheck gate is ST1000-clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* ci: goimports -local gate + Dependabot config (gomod weekly, actions monthly) (#304)

* ci: goimports -local gate + Dependabot config (gomod weekly, actions monthly)

goimports -local github.com/tracebloc/cli now blocks in both loops:
build.yml's lint job (pinned goimports@v0.48.0, same x/tools version as
the deadcode pin) and the Makefile's fmt-check target, with make fmt
extended to auto-fix. .golangci.yml already declared this grouping via
local-prefixes but nothing enforced it — 4 files had drifted (data.go,
data_test.go, ingestion_run_test.go, resources_set_test.go), fixed here
with import-grouping-only diffs.

.github/dependabot.yml extends the org's backend-only Dependabot pilot:
gomod weekly (k8s.io/* + sigs.k8s.io/* grouped, golang.org/x/* grouped),
github-actions monthly. Unlike backend's security-only config, the CLI
takes real version updates — customers install this binary, so staying
current is security posture (see #276). Org-wide rollout decision
flagged to Asad on the PR.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* ci: canonicalize import grouping in data_test.go for the goimports gate

Regroups imports into the layout goimports -local github.com/tracebloc/cli
emits (stdlib / third-party / tracebloc-local). gofmt and goimports only
sort within existing blank-line groups, so the manual groups passed
fmt-check as-is but were not the canonical single-block output; Bugbot and
our precheck both flagged the divergence. Verified idempotent under the
pinned goimports v0.48.0 and green on make fmt-check + go build ./...

Rebased onto ci/279 (post-#303 data.go split): data.go's import block is
already canonical from the #303 split, so its canonicalization here is a
no-op and dropped — this commit now regroups data_test.go only.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>

* ci: flip deadcode gate to blocking; delete the 3 dead #127 leftovers (#313)

* ci: goimports -local gate + Dependabot config (gomod weekly, actions monthly)

goimports -local github.com/tracebloc/cli now blocks in both loops:
build.yml's lint job (pinned goimports@v0.48.0, same x/tools version as
the deadcode pin) and the Makefile's fmt-check target, with make fmt
extended to auto-fix. .golangci.yml already declared this grouping via
local-prefixes but nothing enforced it — 4 files had drifted (data.go,
data_test.go, ingestion_run_test.go, resources_set_test.go), fixed here
with import-grouping-only diffs.

.github/dependabot.yml extends the org's backend-only Dependabot pilot:
gomod weekly (k8s.io/* + sigs.k8s.io/* grouped, golang.org/x/* grouped),
github-actions monthly. Unlike backend's security-only config, the CLI
takes real version updates — customers install this binary, so staying
current is security posture (see #276). Org-wide rollout decision
flagged to Asad on the PR.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* ci: canonicalize import grouping in data_test.go for the goimports gate

Regroups imports into the layout goimports -local github.com/tracebloc/cli
emits (stdlib / third-party / tracebloc-local). gofmt and goimports only
sort within existing blank-line groups, so the manual groups passed
fmt-check as-is but were not the canonical single-block output; Bugbot and
our precheck both flagged the divergence. Verified idempotent under the
pinned goimports v0.48.0 and green on make fmt-check + go build ./...

Rebased onto ci/279 (post-#303 data.go split): data.go's import block is
already canonical from the #303 split, so its canonicalization here is a
no-op and dropped — this commit now regroups data_test.go only.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* ci: flip deadcode gate to blocking; delete the 3 dead #127 leftovers

The deadcode CI step loses continue-on-error (and the Makefile target
its '|| true'): both now run scripts/deadcode-check.sh, which fails on
any function unreachable from ./cmd/tracebloc that isn't declared in
scripts/deadcode-allowlist.txt. The tool itself always exits 0, so the
old advisory step never could have blocked — the gate keys on output.

Deleted (verified still dead with the pinned deadcode@v0.48.0):
- config.clearAll + its three dedicated tests (TestClearAll,
  TestClearAll_HomeError, TestClear) — logout uses Save, nothing else
  ever called it
- push.allCategoryIDs — moved verbatim into category_registry_test.go
  (the registry-pinning tests legitimately iterate every id; the
  shipped binary shouldn't carry the helper)
- submit.isSubmitError — moved into client_test.go as the test-local
  assertion helper it always was (orphaned 'errors' import dropped)

Allowlisted with reasons (the 4 legit findings): Status.String +
JobOutcome.String (fmt-reflection Stringers) and ReadLabelValues +
inferColumnType (di#349 test-only parity harnesses). Stale allowlist
entries warn without failing; line numbers are stripped so edits that
shift code don't red the gate.

Coverage floors still clear after the test deletions (cli 82.9% >= 68,
submit 80.3% >= 72).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants