Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

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

オープン
#1,823 コメント 3 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

@mikolalysenko がすでに取り組んでいます。

2026年10月29日 から。

  • #1824 @mikolalysenko による — オープン

評価

難易度
4/5
見積もり時間
3〜5日
初心者へのやさしさ
48/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
go, rust
領域
backend, devtools

調査の方向性

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.

索引モデルが issue の本文から書いたものです。

説明

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.
主要言語
Rust
スター
8
フォーク
2
平均マージ
19時間 31分
マージ済み PR(30日)
686

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

SocketDev/socket-patch のほかの issue

SocketDev/socket-patch の issue をすべて見る

似ている issue

Rust の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。