Skip to content

Require Go 1.26.10 for the crypto/x509 fix - #32

Merged
tmosleyIII merged 2 commits into
mainfrom
fix/go-1.26.10-x509
Oct 29, 2026
Merged

tmosleyIII merged 2 commits into
mainfrom
fix/go-1.26.10-x509

Conversation

@tmosleyIII

@tmosleyIII tmosleyIII commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

What and why

GO-2026-6809: compromised intermediate certificates were not distrusted by crypto/x509. Fixed in go1.26.10; go.mod required 1.26.9.

Reachable, not merely linked — govulncheck traces it through x509.Certificate.Verify, and flowctl does TLS and mTLS to the control plane:

#1: internal/orchestrator/process.go:568:26: orchestrator.ProcessLogStream.Read
    calls bufio.Reader.Read, which eventually calls x509.Certificate.Verify

Nothing in this repo changed to cause it. The advisory was published after #31 last ran, and the vulncheck gate that #31 added caught it on its first run against main. That is the gate working as designed: it pulls a live vulnerability database, so it can go red with no code change.

Why the go directive and not just toolchain

The one-line change raises the go directive to 1.26.10. With only a toolchain line and a lower directive, GOTOOLCHAIN=local silently builds against the affected standard library — I verified it did. With the directive raised it refuses:

go: go.mod requires go >= 1.26.10 (running go 1.26.9; GOTOOLCHAIN=local)

Failing loudly is the point of a security minimum.

No separate toolchain line is kept: it is redundant once the two match, and go mod tidy removes it — which this repo's own CI tidy check would then fail on.

Contract classification (VER-3)

  • None — no flowctl contract changes. The minimum Go version for building from source rises.

Testing

  • make lint — clean
  • make test — green
  • make test-race — green across all 19 packages
  • make verify-repro — builds still reproduce byte-for-byte
  • ./scripts/govulncheck.sh — clean; the only remaining findings are the two Moby daemon CVEs already covered by .vex/flowctl.openvex.json

The Nix dev shell moves to Go 1.27.3 too

nixpkgs ships go_1_26 as 1.26.9, older than the minimum above, so the dev shell would have left every developer relying on Go downloading a toolchain itself. It now uses go_1_27 — 1.27.3, a stable patch release — which satisfies the minimum directly.

No flake.lock change: the pinned nixpkgs already carries 1.27.3.

An earlier revision of this description claimed nixpkgs had go_1_27 = 1.27rc3 and argued against the move. That was wrong — I read the version from the local flake registry, which is stale, rather than from this repo's lock.

One thing this needed that I did not expect. make lint broke in the shell:

go-1.27.3/share/go/src/math/rand/v2/rand.go:213:17: method must have no type parameters (config)

Not a staticcheck version problem — nixpkgs has the current 2026.2.2. staticcheck links go/types, so a binary built with Go 1.26 cannot parse a 1.27 standard library. The flake rebuilds it with the matching Go:

staticcheck = pkgs.go-tools.override { buildGoModule = pkgs.buildGo127Module; };

CI was never affected — it uses dominikh/staticcheck-action independently of Nix — so this would only have bitten developers running the gate locally.

Verified inside nix develop: Go 1.27.3, make lint clean, 19 packages green, govulncheck clean, reproducible build unchanged.

This closes the flake half of GAP-21; CI still resolves its own Go from go-version-file rather than entering the flake, which is the remaining half.

Pre-existing breakage found on the way (not fixed here)

nix build .#default fails, identically on main:

protoc-gen-go: program not found or is not executable

The derivation runs protobuf generation without the protoc plugins in its nativeBuildInputs. nix develop — the path BUILD-1 documents and CONTRIBUTING describes — is unaffected. Recorded as GAP-26. It wants its own change, and the generation step can probably be dropped from the derivation entirely: the generated code is committed and CI already checks it is current.

🤖 Generated with Claude Code

https://claude.ai/code/session_01H3BjiVyh7ifuS7xSrRUe2m

GO-2026-6809: compromised intermediate certificates were not distrusted
by crypto/x509. Fixed in go1.26.10; we required 1.26.9.

flowctl reaches it through TLS and mTLS to the control plane —
govulncheck traces it via x509.Certificate.Verify — so this is reachable
rather than merely linked.

Nothing in this repo changed to cause it. The advisory was published
after #31 ran, and the vulncheck gate added in that PR caught it on the
first run against main. That is the gate working as intended: it pulls a
live vulnerability database, so it can go red without a code change.

Raises the go directive rather than only the toolchain line, so an older
toolchain refuses to build:

    go: go.mod requires go >= 1.26.10 (running go 1.26.9; GOTOOLCHAIN=local)

With only a toolchain line and a lower go directive, GOTOOLCHAIN=local
silently builds against the affected standard library, which is the
outcome worth preventing for a security fix. No separate toolchain line
is kept: it is redundant once the two match and 'go mod tidy' — which CI
enforces — removes it.

Note for Nix users: nixpkgs ships Go 1.26.6-1.26.9, so the dev shell's
Go is older than the minimum and Go downloads 1.26.10 itself. Recorded
against GAP-21 in the engineering profile, which already tracks CI and
the flake disagreeing about the toolchain.

Verified: govulncheck clean, lint clean, full suite and -race green
across all 19 packages, and the build still reproduces byte-for-byte.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-23T01:06:36.903549Z 4e70d0b PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4e70d0bd83

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread go.mod
go 1.26.1

toolchain go1.26.9
go 1.26.10

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Reject the affected Go 1.27 toolchains

When a developer builds with Go 1.27.0, 1.27.1, or 1.27.2, go 1.26.10 is already satisfied, so the Go command keeps that bundled toolchain rather than switching to 1.26.10; the toolchain documentation defines this directive as only a minimum. Those Go 1.27 versions are also explicitly affected by GO-2026-6809, so such source builds still link the vulnerable standard library. Add enforcement that rejects the affected 1.27 patch range, or require a version such as 1.27.3 that is fixed across the newer release line.

Useful? React with 👍 / 👎.

@tmosleyIII

Copy link
Copy Markdown
Contributor Author

Correction: my note about go_1_27 was wrong

The PR description said nixpkgs carries go_1_27 = 1.27rc3 and argued against moving the dev shell onto it. That was wrong, and I've corrected the description.

I read the version from the local flake registry, which is stale, rather than from this repo's flake.lock. The pinned lock already carries go_1_27 = 1.27.3, a stable patch release — so the dev shell can move onto it with no flake.lock change at all. Apologies for arguing against the right call on bad evidence.

That change is now part of this PR.

What moving the dev shell to Go 1.27.3 needed

A one-word change to flake.nix, plus one thing I did not expect:

staticcheck broke. make lint failed inside the dev shell with:

go-1.27.3/share/go/src/math/rand/v2/rand.go:213:17: method must have no type parameters (config)

Not a staticcheck version problem — nixpkgs has 2026.2.2, the current release. staticcheck links go/types, so a binary built with Go 1.26 cannot parse a 1.27 standard library. nixpkgs builds go-tools with the default Go, so the flake has to rebuild it:

staticcheck = pkgs.go-tools.override { buildGoModule = pkgs.buildGo127Module; };

CI was never affected — it uses dominikh/staticcheck-action independently of Nix — so this would only ever have bitten developers running the gate locally.

Verified inside nix develop: Go 1.27.3, make lint clean, make test green, govulncheck clean, and the build still reproduces byte-for-byte.

Unrelated pre-existing breakage found on the way

nix build .#default fails, and fails identically on main, so this PR does not cause it:

protoc-gen-go: program not found or is not executable
--go_out: protoc-gen-go: Plugin failed with status code 1.

The derivation runs protobuf generation without the protoc plugins in its nativeBuildInputs. nix develop — the path BUILD-1 documents and CONTRIBUTING describes — is unaffected. I have not touched it here; it wants its own change, and I'd suggest dropping the generation step from the derivation entirely since the generated code is committed and CI already checks it is current.

The dev shell was on go_1_26, which nixpkgs ships as 1.26.9 — older than
the 1.26.10 this branch now requires. Every Nix developer would have
relied on Go downloading a toolchain itself.

No flake.lock change: the pinned nixpkgs already carries go_1_27 as
1.27.3, a stable patch release. An earlier note on this PR claimed it
was 1.27rc3; that came from the local flake registry, which is stale,
not from the lock.

staticcheck had to be rebuilt with the same Go. It links go/types, so a
binary built with 1.26 cannot parse the 1.27 standard library, and
make lint failed in the shell with 'method must have no type parameters'
from math/rand/v2. Not a version problem — nixpkgs has the current
2026.2.2 — so the fix is the override rather than a bump. CI was never
affected; it uses dominikh/staticcheck-action independently of Nix.

Verified inside nix develop: Go 1.27.3, lint clean, 19 packages green,
govulncheck clean, build still reproduces byte-for-byte.

Records GAP-26 for a pre-existing failure found on the way:
nix build .#default runs protobuf generation without the protoc plugins
in nativeBuildInputs and fails identically on main. nix develop, the
path BUILD-1 documents, is unaffected.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@tmosleyIII
tmosleyIII merged commit 314a8e4 into main Oct 29, 2026
7 checks passed
@tmosleyIII
tmosleyIII deleted the fix/go-1.26.10-x509 branch October 29, 2026 06:39
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.

1 participant