Repository navigation
Go apply and vendor wire in a patched module whose go.mod raises or adds a requirement without syncing the consumer go.mod/go.sum, so every default go build fails while apply, --check and VEX report success #618
Description
Activity
- addedbugSomething isn't workingSomething isn't workingbughuntFound by a scheduled package-manager bug-hunt agentFound by a scheduled package-manager bug-hunt agentpm:goGo modulesGo modules
on Oct 2, 2026 - added a commit that references this issue
on Oct 2, 2026 mikolalysenko commented
on Oct 2, 2026 CollaboratorAuthorMore actions[agent] Triaged as
priority:p2(Go modules). This isn't a duplicate, and no open or merged PR fixes it. I confirmed it by reading main045d7ec.apply_go_redirect(patch/redirect/golang_local.rs) writes the copy and thereplacebut never reads the replacement's owngo.mod.verify_go_redirect_stateonly cross-checks the consumergo.modrequireset against the patched version and hashes the manifest files. The vendored path invendor/golang.rshas the same gap.Related issues that are not clustered with this one:
- Go apply and vendor break every build in projects with a committed vendor/ directory (modules.txt not synced), while apply --check and VEX report success #343 (vendor/modules.txt not synced) is a different sync gap with a different fix.
- Yarn classic: a patch that adds a dependency to the package's own package.json leaves vendored yarn.lock with a dangling dependency (offline frozen install fails, lock churns), and hosted silently installs without it #591 is the yarn classic analogue in separate code.
Generated by Claude Code
mikolalysenko commented
on Oct 3, 2026 CollaboratorAuthorMore actions[agent] Hosted mode has the same bug, on main
045d7ec(CLI 4.0.0). I reproduced it 2 out of 2 times on go 1.24.7, and once each on 1.21.13, 1.22.12 and 1.26.8.Setup: a local mock patch API returns
view/<uuid>and a/patches/packagegrant with agoproxyregistryOverride, in the same shape ase2e_golang_hosted_build.rs. The module proxy is served overhttp://. The served gopatch zippatch.socket.dev/gopatch/<uuid>@v1.0.0-socketpatch.1keepsmodule example.com/upstream, and its go.mod bumpsrequire example.com/dep v1.0.0→v1.1.0. The consumer's tidy go.mod hasrequire example.com/dep v1.0.0 // indirect.get <uuid> --mode hosted --json --yesexits 0 withstatus: success,redirected: 1,rewrittenFiles: [go.mod, go.sum]andwarnings: []. It adds thereplace … => patch.socket.dev/gopatch/<uuid> v1.0.0-socketpatch.1line and swaps the upstream go.sum pair for the gopatch pair. Theexample.com/deprequirement and its go.sum lines are left at v1.0.0.- A day-2
go build ./...(fresh caches, default-mod=readonly,GOFLAGS=) fails withgo: updates to go.mod needed; to update it: go mod tidyon 1.21.13, 1.22.12, 1.24.7 and 1.26.8. vex --product …exits 0 and attestsnot_affected("Patched via Socket patch … (redirected)") for a project that doesn't build.
So agent, vendored and hosted all wire in the patched module's go.mod requirements without syncing the consumer's go.mod and go.sum. For hosted mode, the rewriter would also need the go.sum lines for any newly required versions (
dep v1.1.0/go.modand the ziph1:). The gopatch grant doesn't carry those today.
Generated by Claude Code
- addedv5-blockerMust resolve before v5: public interface/migration or ordinary patch-install-undo failure.Must resolve before v5: public interface/migration or ordinary patch-install-undo failure.compatibilityPublic CLI/JSON, saved state, upgrades, or package-manager compatibility.Public CLI/JSON, saved state, upgrades, or package-manager compatibility.and removed
on Oct 9, 2026 mikolalysenko commented
on Oct 9, 2026 CollaboratorAuthorMore actionsv5 release blocker (P1). When the patch changes Go requirements, the normal next build must work. Update or explicitly guide the required go.mod/go.sum refresh.
This follows the maintainer's release scope: one normally completing CLI instance, prioritizing valid-lockfile patch/install behavior, compatibility, and actionable CLI UX.
mikolalysenko commented
on Oct 9, 2026 CollaboratorAuthorMore actions[agent] Claiming for v5 blocker burn-down (shared root cause: Go redirect wiring edits only the consumer go.mod replace; vendor/modules.txt and the consumer requirement graph/go.sum are never synced or checked). Branch: agent/v5-go-consumer-sync. Claim-ID: 2026-10-09T16:41:32Z-ccb36f
[agent] Found by the scheduled Go modules bug-hunt routine (ledger #317).
Summary
When a Go patch changes the patched module's own
go.mod(the common security-fix shape: bump a vulnerable dependency, e.g.require example.com/dep v1.0.0→v1.1.0, or add a newrequire), agentapplyand vendoredvendorwrite the directoryreplaceto.socket/go-patches/…/.socket/vendor/golang/…and exit 0. Go reads the requirements from the replacement directory'sgo.mod, so the module graph changes, but the consumer'sgo.modandgo.sumare left as they were. Since Go 1.16 the default is-mod=readonly, so the next plaingo buildfails:go: updates to go.mod needed; to update it: go mod tidymissing go.sum entry for module providing package example.com/dep (imported by example.com/upstream)Meanwhile
apply --check/vendor --checkexit 0 andvexattestsnot_affected.Impact
CI (and any default
go build/go test) breaks right after a "successful" apply or vendor. A user has to rungo mod tidy(or build with-mod=mod), which changesgo.mod/go.sumoutside socket-patch's ownership. The--checkaudit, meant as CI's gate, doesn't catch it. Yarn has the same class of bug (#591).Repro (agent mode, hermetic file GOPROXY, hand-staged manifest)
Variant: a patch that adds
require example.com/dep v1.0.0(and imports it) givesmissing go.sum entry for module providing package example.com/depon the default build, with the same apply/--check exit 0.Vendored mode: the same patched module served as a granted tarball from a mock patch service (
SOCKET_VENDOR_URL=http://127.0.0.1:<port>,POST /patch/package→{"status":"granted","artifacts":[{"kind":"tarball",…,"integrity":{"sha512":…}}]}):vendorexit 0 with no warnings, defaultgo build→updates to go.mod needed,vendor --checkexit 0.Expected vs actual
replaceand that "apply --checkgives CI a read-only audit that the committed redirects still match the manifest". So after a successful apply/vendor the project should build with the default flags, or the CLI should refuse / warn (for example, run the equivalent ofgo mod tidyfor the replaced module's new requirements, or report thatgo.mod/go.sumneed updating), and--checkshould fail while the graph is out of sync. The docs don't list a patched modulego.modas a limitation.--check0, VEXnot_affected. The next defaultgo buildfails.Matrix (Linux, main
045d7ec, 4.0.0)Hosted mode is untested. The service builds the replacement zip and its
/go.modhash, so the same missing requirement sync probably applies there.Suspect code
crates/socket-patch-core/src/patch/redirect/golang_local.rs:169(apply_go_redirect): writes the copy and the replace, but never compares the copy'sgo.modrequirements against the consumer graph.crates/socket-patch-core/src/vendor/golang.rs:210(vendor_go_module): same for the vendored tree.crates/socket-patch-core/src/patch/redirect/golang_local.rs:452(verify_go_redirect_state):--checkonly hashes the manifest's files.No first bad version: 3.3.0 rejects this manifest shape (see the ledger).