Skip to content

chore(deps): provider-runtime v1.7.0 — close called x/net and x/crypto vulnerabilities; require Go 1.26 - #28

Merged
braghettos merged 1 commit into
mainfrom
chore/provider-runtime-v1.7.0
Oct 29, 2026
Merged

braghettos merged 1 commit into
mainfrom
chore/provider-runtime-v1.7.0

Conversation

@braghettos

Copy link
Copy Markdown

What changed

  • github.com/krateo-platformops/provider-runtime v1.4.0 -> v1.7.0, then go mod tidy. Transitive moves: golang.org/x/net v0.57.0 -> v0.62.0, golang.org/x/crypto v0.55.0 -> v0.58.0, other golang.org/x/*, otel v1.43.0 -> v1.45.0, protobuf v1.36.12, logr v1.4.4.
  • go.mod: go 1.26.0 plus toolchain go1.26.10. The go line stays at the floor the runtime requires, so this module imposes nothing more on importers. The toolchain line makes local builds and scans use a patched stdlib.
  • Dockerfile: golang:1.25.6-bookworm -> golang:1.26-bookworm, the floating 1.26 tag rather than a pinned patch release.
  • CI is unchanged: both workflows use actions/setup-go with go-version: 'stable', which already satisfies go >= 1.26.0.
  • No code change was needed.

Why

  • Vulnerabilities this code calls. v1.7.0 closes five golang.org/x/net HTTP/2 vulnerabilities, reached via controller-runtime/client-go (manager.New, the dynamic client). It also closes two golang.org/x/crypto/ssh channel-DoS vulnerabilities, reached from Repo.Push (internal/clients/git/git.go:775) via go-git's SSH transport.
  • Runtime behaviour picked up since v1.4.0:

govulncheck

go run golang.org/x/vuln/cmd/govulncheck@latest ./.... The "before" run used GOTOOLCHAIN=go1.26.10 so that stdlib findings would not hide module findings.

Called by this code In imported packages, not called In required modules, not called
main (before) 7: GO-2026-6603, -6610, -6611, -6612, -6617 (x/net v0.57.0, fixed in v0.60.0); GO-2026-6354, -6355 (x/crypto v0.55.0, fixed in v0.56.0) 1 3
this branch (after) 0 0 1: GO-2026-5932 (x/crypto v0.58.0, Fixed in: N/A)

Tests

Run locally on go1.26.10, Docker available:

  • go build ./...: OK
  • go vet ./... and go vet -tags=unit,integration ./...: OK
  • go test -race -tags=unit,integration -p 1 -timeout 30m ./... (the CI command): all 9 packages with tests pass, integration suites included. internal/controllers/repo took 361s and internal/controllers/localresource took 301s. No data races were reported.

Observe audit (provider-runtime managed reconciler contract)

Both ExternalClients use pkg/reconciler. I checked every error return in each Observe against the contract in provider-runtime's docs/overview.md. No defect found; nothing to split into a follow-up.

Both Creates converge. SyncRepos and SyncLocalResources re-clone the target and copy the content. When the tree is clean, Repo.Commit returns NoErrAlreadyUpToDate, and both callers adopt the current head as the external name without committing (repo.go:449-457, localresource.go:542-549). So answering ResourceExists:false for a resource that exists would not duplicate a commit. Every reachable error in either Observe is a remote read of a repository that Create/Update need as well. If that read keeps failing, Create fails the same way, so answering ResourceExists:false instead of erroring would gain nothing.

internal/controllers/repo/repo.go Observe (line 124)

  • :127 errNotRepo: a type assertion that cannot fail in practice.
  • :158 is the existence check: an empty external name answers ResourceExists:false with a nil error. Nothing before it errors, and it reads only what the object records (status targetCommitId, or the external name annotation, since Repo create wedges on external-create-pending when the status write after a successful push conflicts (0.15.4) #26). This matches the core-provider#236 pattern.
  • :175 GetLatestCommitRemote on the origin, and :188 IsInGitCommitHistoryContext on the target, are both after the existence check, i.e. only for a Repo that records a pushed commit. Both are remote reads, so a retry can answer them. A target branch that is missing answers false, not an error (git.go:354-356). The cases that persist are an empty or missing target repository, a missing origin branch (ErrBranchNotFound), or bad credentials. In each, SyncRepos fails on the same remote, so Update (or Create) would hit the same failure. The origin read comes before the target read even though existence does not depend on the origin. That ordering could only matter when a create is pending and the external name is already persisted, i.e. when the runtime's external-create-succeeded write itself failed. In that case the error is still transient, and v1.6.0 now names the pending create in Synced.
  • :210 the "target commit ... unreachable while enableUpdate is false" error is a deliberate, permanent error that needs a human decision (A rewritten or recreated target repo orphans every recorded TargetCommitId and hard-fails Observe permanently when enableUpdate is false #23/fix(repo): say why a target commit became unreachable instead of implying a bad pin (#23) #24, pinned by TC12/TC13). It is not an ambiguity that nothing can resolve.

internal/controllers/localresource/localresource.go Observe (line 166)

  • :169 type assertion, as above.
  • :228 IsFuncInGitCommitHistory on the target comes before the existence check at :245. It is the existence lookup itself: it scans the history for this resource's commit footer. Its errors are the clone/HEAD/log steps of a remote read, so they are transient. The local steps that could fail permanently, footer parsing (:210) and CalculateLocalResourceSpecHash (:219), never return an error from Observe. The callback treats them as "no match". A missing branch answers "not found" (git.go:444-446). If the remote failure persists (empty or missing target repository, bad credentials), it holds a pending create, but syncWithRetry would fail on the same clone, so answering ResourceExists:false would only turn the held state into external-create-failed and would not unblock anything. Answering would be safe here because Create converges. It is optional hardening, not a contract defect.

Outside the scope of the error-return audit, not changed here, and not verified by a test: in LocalResource.Observe, when the target history no longer contains this resource's footer (hash.IsZero() && !hasGitProviderPreviuslyCommitted, the else at :241) but status.targetCommitId is set, it falls through to ResourceExists:true, ResourceUpToDate:true (:252-257, after the external-name check at :245 passes). A LocalResource whose commit was discarded by a recreated or force-pushed target would then report Available and not re-commit. That may be intended. It is worth a look as its own issue.

🤖 Generated with Claude Code

https://claude.ai/code/session_016RAxvjZaJueRyPRKkxVde4

…o vulnerabilities; require Go 1.26

govulncheck on main finds 7 vulnerabilities this code calls: five golang.org/x/net HTTP/2 ones
(GO-2026-6603/6610/6611/6612/6617, reached through client-go) and two golang.org/x/crypto/ssh
channel DoS ones (GO-2026-6354/6355, reached from Repo.Push via go-git's SSH transport).
provider-runtime v1.7.0 closes them: it moves x/net to v0.62.0 and x/crypto to v0.58.0, and
requires go >= 1.26.0. After the bump govulncheck reports 0 called; the one remaining finding in
a required module (GO-2026-5932, x/crypto) has no fix and is not reached.

Runtime changes picked up between v1.4.0 and v1.7.0:
- v1.5.2: a resource-version conflict from Create stamps external-create-failed, so the create is
  retried on the next reconcile instead of waiting out the 2-minute recovery grace.
- v1.6.0: while Observe errors on an unresolved create, Synced names the pending create as well
  as the Observe error.
- v1.7.0: dependency updates only; no API or behaviour change from v1.6.0.

- go.mod: go 1.26.0 plus toolchain go1.26.10. The go line stays at the floor the runtime
  requires so this module imposes nothing more on importers; the toolchain line makes local
  builds and scans use a patched stdlib.
- Dockerfile: golang:1.26-bookworm, the floating 1.26 tag, rather than pinning a patch release.
  CI already uses setup-go with go-version 'stable' and is unchanged.

No code change was needed. go build, go vet (also with -tags=unit,integration) and the CI test
command (go test -race -tags=unit,integration -p 1 ./...) pass, integration tests included.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016RAxvjZaJueRyPRKkxVde4
@braghettos
braghettos merged commit 19577e9 into main Oct 29, 2026
3 checks passed
@braghettos
braghettos deleted the chore/provider-runtime-v1.7.0 branch October 29, 2026 05:47
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