Skip to content

fix(golang): require Go 1.26.10 so crypto/x509 blocks the eMudhra intermediates - #1302

Merged
tobyhede merged 1 commit into
mainfrom
claude/project-thread-ktk902
Oct 20, 2026
Merged

tobyhede merged 1 commit into
mainfrom
claude/project-thread-ktk902

Conversation

@tobyhede

@tobyhede tobyhede commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

Requested by Toby · project thread

Closes #1300

Summary

Go 1.26.10 and 1.27.3 are the first releases whose crypto/x509 rejects chains through the eight compromised eMudhra intermediate CAs (CVE-2026-111943, golang/go#82345). A Go SDK binary built with an older toolchain would still accept such a chain, so whoever holds those keys could impersonate ZeroKMS or the auth endpoints to it.

  • languages/golang/go.mod: go 1.26.0 → go 1.26.10
  • root mise.toml: go = "1.26" → go = "1.26.10", with a comment saying why it is pinned to the patch
  • encrypt/README.md, cmd/stashgen/README.md, encrypt/doc.go: the stated minimum goes from "Go 1.26 or later" to 1.26.10 (or 1.27.3 on 1.27)
  • AGENTS.md: the toolchain note now says Go 1.26.10

Why go 1.26.10 and not a toolchain go1.26.10 directive

The SDK is a library that other modules import, so the directive has to reach consumers:

  • go is the only directive a dependency's go.mod passes on to the modules that import it. When a consumer runs go get on this module, their own go line goes up to 1.26.10. Under the default GOTOOLCHAIN=auto, an older local Go then downloads 1.26.10 and switches to it. Under GOTOOLCHAIN=local, it refuses to build. Both are the outcomes we want.
  • A toolchain directive only applies in the main module. It would protect builds inside this repo and nobody who imports the SDK. It also wouldn't raise the language minimum, so a 1.26.0 toolchain with GOTOOLCHAIN=local would still build the module.

Raising go does make 1.26.10 a hard requirement, but that is the point of this fix. go mod tidy -diff is clean, so no toolchain line gets added.

One gap a minimum can't close: 1.27.0 to 1.27.2 are higher than 1.26.10 but still vulnerable. The READMEs and doc.go say so.

CI and release

tests-golang.yml (setup-go, from the go = "…" line it reads with sed) and release-golang.yml (mise-action) both take Go from the root mise.toml pin, so they now build with 1.26.10. The sed still matches the new value. No guard test under scripts/__tests__ or scripts/go-release-version.mjs pins the Go toolchain version.

Changeset

None. The Go module is released by hand with release-golang.yml, not through Changesets. No file under skills/ mentions a Go version, so the stash tarball doesn't change.

Verification

Run locally with GOTOOLCHAIN=go1.26.10 (the toolchain downloaded fine):

  • Built all five WASI guests: release, deterministic-kms, eql, eql,deterministic-kms, and auth
  • scripts/go-binding-test.sh languages/golang (the go:test body): gofmt, go vet, go test ./... on amd64, and GOARCH=386 go test ./.... All pass.
  • go generate ./...: no diff
  • go mod tidy -diff: clean
  • pnpm run test:scripts: 79 files, 1415 passed, 1 skipped (already skipped before this change)

Not run: golangci-lint (not installed here), and the live Go tests that need credentials.


Generated by Claude Code

Summary by CodeRabbit

  • Documentation

    • Updated Go setup requirements to Go 1.26.10 or later, or Go 1.27.3 or later on the Go 1.27 release line.
    • Documented the security protection provided by these versions against compromised certificate authorities.
    • Clarified automatic toolchain switching behavior when GOTOOLCHAIN=auto is enabled.
    • Added guidance not to use Go 1.27.0–1.27.2.
  • Chores

    • Updated the project’s required and pinned Go toolchain version to 1.26.10.

…ermediates

Go 1.26.10 and 1.27.3 are the first releases whose crypto/x509 rejects
chains through the eight compromised eMudhra intermediate CAs
(CVE-2026-111943, golang/go#82345). A program built with an older
toolchain would accept a chain through them, which would let the key
holder impersonate ZeroKMS or the auth endpoints to the Go SDK.

- languages/golang/go.mod: `go 1.26.0` -> `go 1.26.10`. The `go` line is
  the one directive a dependency's go.mod imposes on its consumers: `go get`
  raises the consumer's own `go` line to it, and GOTOOLCHAIN=auto then
  fetches a fixed toolchain. A `toolchain` directive is honoured only in
  the main module, so it would protect this repo's builds and nobody
  importing the SDK.
- mise.toml: pin go to "1.26.10" rather than the floating "1.26", so CI
  (tests-golang.yml and release-golang.yml both resolve Go from this pin)
  and local builds cannot pick an older patch from a cache.
- The encrypt and stashgen READMEs, encrypt/doc.go and AGENTS.md state
  the new minimum, and note that 1.27.0 to 1.27.2 are also vulnerable,
  which a minimum version cannot express.

Closes #1300

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014Givi9JCPVy1s8ZL8oPo6D
@tobyhede
tobyhede requested a review from a team as a code owner October 20, 2026 21:06
@tobyhede tobyhede self-assigned this Oct 20, 2026
@changeset-bot

changeset-bot Bot commented Oct 20, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 7b4ceef

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai

coderabbitai Bot commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Essentials
  • Run ID: 97b22c2b-7968-47e9-9ad8-53df7a0868d4
📥 Commits

Reviewing files that changed from the base of the PR and between 214d24d and 7b4ceef.

📒 Files selected for processing: 6
  • AGENTS.md
  • languages/golang/cmd/stashgen/README.md
  • languages/golang/encrypt/README.md
  • languages/golang/encrypt/doc.go
  • languages/golang/go.mod
  • mise.toml

Included review availability: This review used your included allowance. 4 included reviews remain after this review. Your included PR review attempts over the past 7 days set your current allowance at 5 reviews per hour.

📝 Walkthrough

The Go module minimum and pinned toolchain are now Go 1.26.10. Documentation specifies Go 1.26.10 or Go 1.27.3 and describes the associated crypto/x509 security behavior.

Changes: Go toolchain security minimum

Layer / File(s) Summary
Set and document the secure Go minimum
languages/golang/go.mod, mise.toml, AGENTS.md, languages/golang/cmd/stashgen/README.md, languages/golang/encrypt/README.md, languages/golang/encrypt/doc.go
The module requirement and toolchain pin now use Go 1.26.10. The documentation specifies Go 1.26.10 or Go 1.27.3 and notes that Go 1.27.0–1.27.2 must not be used.

Priority: ⬆️ High

Estimated code review effort: 2 (Simple) | ~8 minutes

Change: Bug fix · Severity of issue fixed: High

Suggested reviewers: coderdan

Merge Risk: ⚪ Minimal · up to 7b4ce

No actionable merge-blocking risk remains from the reviewed changes.

Pre-merge checks: Passed 5
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely describes the main change: requiring Go 1.26.10 to ensure crypto/x509 blocks the compromised eMudhra intermediates.
Linked Issues check Passed Issue #1300 requires Go 1.26.10 or a later non-vulnerable release, a safe root toolchain pin, version documentation, guard-reference review, and passing generation and Go tests. The diff changes `lang…
Out of Scope Changes check Passed The changes stay within issue #1300. They update the Go module minimum, the shared Go toolchain pin, related Go-version documentation, and the toolchain rationale. They do not change the Rust TLS veri…
Docstring Coverage Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 1…
Full details: Linked Issues check

Explanation

Issue #1300 requires Go 1.26.10 or a later non-vulnerable release, a safe root toolchain pin, version documentation, guard-reference review, and passing generation and Go tests. The diff changes languages/golang/go.mod to go 1.26.10 and pins root mise.toml to 1.26.10 with the security rationale. It updates AGENTS.md, both SDK READMEs, and encrypt/doc.go. The PR reports that workflow references consume the root pin, no guard test pins another Go version, go generate ./... produces no diff, and the Go tests pass. The toolchain rationale also addresses the consumer requirement.

Full details: Out of Scope Changes check

Explanation

The changes stay within issue #1300. They update the Go module minimum, the shared Go toolchain pin, related Go-version documentation, and the toolchain rationale. They do not change the Rust TLS verifier or unrelated product behavior.

Full details: Docstring Coverage

Explanation

No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 1 files. (5 skipped: 5 unsupported.)

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@cipherstash-agent cipherstash-agent left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review attestation: automated review by Claude Code (/code-review medium, then company-skills:cross-check-review-findings) at head 7b4ceef.

Result: no findings. No critical or blocking issues.

Checked against the head commit:

  • go.mod raises go to 1.26.10, the right directive for a library. A toolchain line would not reach importers.
  • mise.toml pins go = "1.26.10". The sed -n 's/^go = "\(.*\)"/\1/p' step in tests-golang.yml still matches it, and release-golang.yml takes Go from the same pin.
  • No other docs or workflows name the old minimum. The remaining go 1.26 lines are the stashgen/testdata fixture modules and refusal_test.go, which are not shipped.
  • No skills/ file mentions a Go version, and the Go module releases outside Changesets, so no changeset is needed. The changeset-bot warning can be ignored.
  • No existing human review feedback to cross-check. The only comments are bot notices.

Not verified: I could not independently confirm that 1.26.10 / 1.27.3 are the first releases with the eMudhra block (CVE-2026-111943 / golang/go#82345). That rests on the PR description.

Review source: Claude Code (automated). The scripted feedback fetch hit a GraphQL 403 here, so existing comments and reviews were read through the REST-backed GitHub tools instead.


Generated by Claude Code

@github-actions

Copy link
Copy Markdown
Contributor

Mutation testing (cargo-mutants, --in-diff, stack-auth + stack-encrypt)

No mutants were generated for the changed lines.

@freshtonic freshtonic left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This looks good. It would be great if there were tests but I can't see how it would be possible: we'd need the compromised keys to attempt a TLS connection in order to see it rejected.

Comment on lines +11 to +15
This needs Go 1.26.10 or later (or 1.27.3 or later on 1.27):
those are the first releases whose `crypto/x509` blocks the compromised eMudhra intermediate CAs
([CVE-2026-111943](https://github.com/golang/go/issues/82345)).
The module's `go` line requires 1.26.10, so under the default `GOTOOLCHAIN=auto` an older local Go downloads and switches to 1.26.10.
A minimum cannot exclude 1.27.0 to 1.27.2, which are also vulnerable: do not build with those.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nice

@cipherstash-bot cipherstash-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.

Recommendation: 🟢 merge as it is

Nothing must change before merging. The go 1.26.10 line is the correct directive for a library, and the version pins and docs agree. Two follow-ups can wait: add a test that guards the version floor, and consider a run-time check for Go 1.27.0 to 1.27.2, which go.mod cannot exclude.

How this review was made
Agent Model Review type Result
claude claude-opus-5-5 test-gap 1 found, 1 posted
claude claude-opus-5-5 golang 1 found, 1 posted
codex gpt-5.6-terra test-gap 0 found, 0 posted
codex gpt-5.6-terra golang 0 found, 0 posted

Synthesis: claude-sonnet-5-5 merged the findings, removed duplicates and dropped findings it could not confirm in the code. 0 posted finding(s) were raised by two or more models.

Plain language: claude-sonnet-5-5 read every comment as a new reader would. No comment had a problem that stopped the reader acting, so none was rewritten.

Stack: not part of a stack.

Context loaded: the description, 1 linked issue(s) and 6 discussion entries.

Comment thread mise.toml
# 1.26.10 is the first 1.26 release whose crypto/x509 blocks the compromised
# eMudhra intermediates (CVE-2026-111943, #1300), and a floating "1.26" could
# resolve an older patch from a cache. Keep it at or above go.mod's `go` line.
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.

Fix in a follow-up: no test checks the Go 1.26.10 security floor in go.mod and mise.toml.

Impact: The fix for CVE-2026-111943 is two version strings. A later change can lower the go line in languages/golang/go.mod, or set this pin back to a floating "1.26". CI still passes in both cases. A Go SDK binary built after that change can accept certificate chains through the compromised eMudhra intermediates again.

Evidence: No file in scripts/__tests__/ reads the go line of go.mod or the go = "…" pin in mise.toml. go-module-path.test.mjs and go-release-version.test.mjs read only the module line. The comment above this line says "Keep it at or above go.mod's go line", but no test checks that rule.

Fix: Add scripts/__tests__/go-toolchain-floor.test.mjs. It must check three things: the go.mod go line is 1.26.10 or higher; the mise.toml pin is a full X.Y.Z version; the mise.toml pin is at or above the go.mod line.

Found by 1 model: claude

Comment thread languages/golang/go.mod
module github.com/cipherstash/stack/languages/golang

go 1.26.0
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.

Fix in a follow-up: a binary built with Go 1.27.0, 1.27.1 or 1.27.2 still trusts the compromised eMudhra intermediates, and the SDK does not detect it.

Impact: The go 1.26.10 line forces a toolchain switch only when the local Go is older than 1.26.10. Go 1.27.0 to 1.27.2 are newer, so go get and go build keep them. A consumer on an unpatched Go 1.27 builds a vulnerable binary. That binary uses http.DefaultTransport by default (encrypt/client.go:75, auth/transport.go:81). A holder of the compromised keys can then impersonate ZeroKMS or the auth endpoint. Only the READMEs warn about this range.

Evidence: In go/version order, go1.27.0 is greater than go1.26.10, so a minimum in go.mod cannot exclude it. The PR description lists this gap as known.

Fix: Check runtime.Version() before the first request, for example in encrypt.NewClient and the auth store constructor. Use go/version: return an error when the version is at least go1.27 and below go1.27.3. Treat an invalid (devel) version as allowed.

Found by 1 model: claude

@tobyhede
tobyhede merged commit 073651f into main Oct 20, 2026
48 checks passed
@tobyhede
tobyhede deleted the claude/project-thread-ktk902 branch October 20, 2026 22:57
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.

Go: require Go ≥ 1.26.10 so crypto/x509 blocks the compromised eMudhra intermediates

5 participants