Hacktoberfest 2026 : les issues que les mainteneurs ont marquées pour octobre, ouvertes et accessibles aux débutants. Parcourir les issues Hacktoberfest

Go apply, apply --check and vex treat a module that is only another module's replace target as built, so the patch is reported applied and attested while go builds the unpatched code

Fermée
#1,823 3 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Les mainteneurs répondent en général sous 1 jour

@mikolalysenko y travaille déjà.

Depuis le 29/10/2026.

  • #1824 par @mikolalysenko — ouverte

Évaluation

Difficulté
4/5
Temps estimé
3-5 jours
Accessibilité débutants
48/100
Type d'issue
Bug
Clarté
Clairement spécifiée
Activité
Active
Stack technique
go, rust
Domaine
backend, devtools

Piste de recherche

Start with crates/socket-patch-core/src/vendor/go_build_list.rs, especially the selection logic around lines 90–99, then trace the callers in patch/redirect/golang_local.rs and vex/discover/golang.rs. Reproduce the reported case with a module named only as a replace target and compare apply, apply --check, and VEX results with workspace mode. Done means those paths refuse or otherwise avoid claiming the patch is active when Go builds the unpatched target.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Description

agent:claimed agent:triaged bug bughunt pm:go priority:p2

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

Summary

A common Go fork idiom is replace other.com/fork v1.0.0 => example.com/upstream v1.0.0 (or the versionless replace other.com/fork => example.com/upstream v1.0.0). go downloads example.com/[email protected] into the module cache and records its zip and /go.mod lines in go.sum under the target's path, but example.com/upstream is not a module of the build: go list -m all shows only other.com/fork v1.0.0 => example.com/upstream v1.0.0. go doesn't chain replaces, so a replace of example.com/upstream is ignored.

In module mode (no go.work), with a patch for pkg:golang/example.com/[email protected], socket-patch:

  • apply writes replace example.com/upstream v1.0.0 => ./.socket/go-patches/example.com/[email protected] and exits 0 ("1 of 1 targeted patch applied"),
  • apply --check says "Patches are in sync" (exit 0),
  • vex emits not_affected / inline_mitigations_already_exist (exit 0),

while go run / go build -mod=readonly link the unpatched code.

Impact

A false VEX attestation for a vulnerable dependency, and a green apply --check in CI. Replacing a module with a fork is common (abandoned upstreams, security forks), and the fork's code is exactly what Socket would patch.

Repro (Linux, go 1.24.7, hermetic file GOPROXY serving example.com/upstream v1.0.0 whose lib.go returns "PRISTINE"; hand-staged .socket/manifest.json + blob that makes it return "PATCHED", as in e2e_golang_build.rs)

mkdir app && cd app
cat > go.mod <<'EOF'
module example.com/app

go 1.21

require other.com/fork v1.0.0

replace other.com/fork v1.0.0 => example.com/upstream v1.0.0
EOF
cat > main.go <<'EOF'
package main

import (
	"fmt"
	u "other.com/fork"
)

func main() { fmt.Println("app:", u.Greeting()) }
EOF
go mod tidy                      # go.sum: example.com/upstream v1.0.0 h1:… and /go.mod h1:…
# stage .socket/manifest.json + blob for pkg:golang/example.com/[email protected]
socket-patch apply --offline --ecosystems golang   # exit 0, 1 of 1 applied; go.mod gains the replace
go list -m all                   # example.com/app / other.com/fork v1.0.0 => example.com/upstream v1.0.0
GOFLAGS=-mod=readonly go run .   # app: PRISTINE
socket-patch apply --check --ecosystems golang     # exit 0, "Patches are in sync"
socket-patch vex --product pkg:golang/example.com/app   # status not_affected, exit 0

Expected vs actual

docs/ecosystems.md, "Go: directory replaces and go.sum": "A replace names an exact module version, so it only works while the build selects that version. socket-patch reads which version that is from go.mod and go.sum … the require line in a go 1.17+ module … apply and scan --mode hosted refuse to write a replace for any other version." Here no require names example.com/upstream at all. Expected: apply refuses (as it does with "is not in this project's build graph … nothing written" when there's no zip line), apply --check fails, and vex leaves the patch out. Alternatively, patch it through the replace that actually selects the code (other.com/fork v1.0.0 => ./.socket/go-patches/…). Actual: all three report success while the build is unpatched. CLI_CONTRACT: vex must not attest a patch that isn't in effect.

Workspace mode is correct: the same module as a go.work member (apply from the member or the root) refuses with "not in this project's build graph", because GoWorkspace::selection walks the module graph.

OS × version

OS go go directive replace form main ecd4924 v5.0.1
Linux 1.21.13 1.21 versioned fail —
Linux 1.24.7 1.16 versioned / versionless fail / fail —
Linux 1.24.7 1.21 versioned / versionless fail / fail fail
Linux 1.26.8 1.21 versioned fail —
Linux 1.24.7 go.work member versioned refuses (correct) —
macOS / Windows — — — untested (no probe branch this run) —

Untested: vendored (vendor uses the same selection_refusal) and hosted (patch/redirect/mod.rs:9633 calls the same go_build_list::select), which probably behave the same.

First bad release

Not a recent regression: v5.0.1 shows it too.

Suspect code

  • crates/socket-patch-core/src/vendor/go_build_list.rs:90: in a pruned (go 1.17+) graph, None if zips.contains(&version) => Selection::Selected. And :94-99 for go < 1.17: a go.sum zip line counts as evidence that the module is built. A zip line also appears for a version that is only a replace target, under the target's path. The selection should ignore go.sum lines for a module/version that go.mod names only on the right-hand side of a replace (or, as workspace mode does, walk the graph).
  • Callers: patch/redirect/golang_local.rs:669 (selection_refusal, used by apply and vendor), vex/discover/golang.rs:300, patch/redirect/mod.rs:9633 (hosted).
  • Open PR #1698 mentions "unused replacements" in its audits; I couldn't tell whether it covers this shape.
Langage dominant
Rust
Étoiles
8
Forks
2
Merge moyen
19 h 12 min
PR mergées (30 j)
709

Préparer son environnement

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Autres issues de SocketDev/socket-patch

Toutes les issues de SocketDev/socket-patch

Issues similaires

Plus d'issues Rust

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.