Skip to content

Agent-mode Go vex attests not_affected after go get upgrades the patched module, although the go-patches replace no longer applies and the build links the unpatched code #391

Description

[agent] Found by the scheduled Go modules bug-hunt routine (ledger #317).

Summary

After an agent-mode apply of a Go patch for M@v1.0.0, go.mod gets replace M v1.0.0 => ./.socket/go-patches/M@v1.0.0. If a developer or Dependabot then runs go get M@v1.0.1 (or any other version), go.mod requires M v1.0.1. The version-pinned replace then no longer matches, and go build links the unpatched upstream module.

apply --check catches this correctly. It exits 1 with ResolvedVersionMismatch: "patched version v1.0.0 is not the required version (go.mod requires v1.0.1) — go would link the UNPATCHED module". But socket-patch vex still exits 0 and writes a not_affected statement for the patch's CVE.

Impact

The OpenVEX document tells scanners the product is not affected by a CVE whose vulnerable code is compiled into the binary. This is the one failure VEX must never have. Upgrade drift is routine: Dependabot and Renovate bump go.mod versions all the time.

Repro (Linux, go 1.24.7, hermetic file GOPROXY)

The fixture has the same shape as crates/socket-patch-cli/tests/e2e_golang_build.rs: module example.com/upstream with versions v1.0.0 and v1.0.1, both containing Greeting() = "PRISTINE", plus a hand-staged .socket/manifest.json and blob that patch lib.go in v1.0.0 to "PATCHED", with setup.manual: ["golang"].

export GOPROXY=file://$T/proxy GOMODCACHE=$T/modcache GOSUMDB=off GOFLAGS=-mod=mod GOTOOLCHAIN=local
cd consumer                       # go.mod: require example.com/upstream v1.0.0
socket-patch apply                # exit 0; replace example.com/upstream v1.0.0 => ./.socket/go-patches/...
go run .                          # OUT: PATCHED
go get example.com/upstream@v1.0.1
go run .                          # OUT: PRISTINE   <- unpatched code linked
socket-patch apply --check        # exit 1: "patched version v1.0.0 is not the required version (go.mod requires v1.0.1)"
socket-patch vex --output v.json  # exit 0, 1 statement
grep status v.json                # "status": "not_affected"

It reproduced 3 times on main in fresh fixtures: with go get @v1.0.1, go get @v1.1.0, and with go build as the oracle instead of go run.

Expected vs actual

  • Expected: README ("socket-patch vex", step 2): "re-checks each patch's bytes so the attestation only covers patches that are actually applied". CLI_CONTRACT.md property 7 also requires on-disk verification. A go-patches replace whose LHS version no longer matches the required version is inert, so vex should omit the patch with a warning, the same way apply --check already reports the drift.
  • Actual: vex exit 0, not_affected.

For comparison, vendored mode handles the same drift correctly: after vendor plus go get M@v1.0.1, vex omits the patch with vendor_unwired.

OS × version

OS go socket-patch reproduces
Linux 1.24.7 main f6b7fb9 yes (3×)
Linux 1.24.7 4.0.0 release yes (needs --product, since 4.0.0 doesn't auto-detect it here)

The defect is in pure go.mod parsing logic, so it doesn't depend on the OS. It isn't a regression: 4.0.0 behaves the same way, and 3.3.0 doesn't accept the hand-staged manifest shape.

Suspect code

crates/socket-patch-cli/src/commands/vex.rs:1333 synthesize_go_patches: for each socket-owned .socket/go-patches replace, it builds the PURL from the replace's LHS version (line 1351) and records the copy dir for dir-hash verification. It never compares that version with the go.mod require (or the selected build-list version). The copy dir still hashes as patched, so verification passes. The drift check already exists as Drift::ResolvedVersionMismatch in crates/socket-patch-core/src/patch/redirect/golang_local.rs:115, but vex doesn't use it.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    agent:triagedbugSomething isn't workingbughuntFound by a scheduled package-manager bug-hunt agentpm:goGo modulespriority:p2

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions