Skip to content

Go settings written with go env -w are ignored: GOPRIVATE modules are requested from proxy.golang.org, a GOPROXY mirror is bypassed, and a GOMODCACHE cache is not found #344

Description

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

Summary

socket-patch reads Go settings only from the process environment. It ignores the Go environment file that go env -w writes ($GOENV, by default ~/.config/go/env, ~/Library/Application Support/go/env, %AppData%\go\env). go env -w is how Go's own docs tell users to set GOPRIVATE and GOPROXY. So when those settings live in that file:

  1. GOPRIVATE / GONOPROXY set with go env -w → the private module path goes to proxy.golang.org. vendor on a cold cache fetches https://proxy.golang.org/<private module>/@v/<ver>.zip. With the same value as an env var, it correctly refuses (matches GOPRIVATE … not fetching it, the Stop hosted Go redirects claiming unpatched deps #252 B11 fix). go itself never contacts a proxy for these modules. Keeping private module paths away from the public proxy is exactly what GOPRIVATE is for.
  2. GOPROXY set with go env -w (a corporate mirror) is bypassed. socket-patch fetches from proxy.golang.org instead. The mirror sees 0 requests while go build on the same machine fetches everything from it. In a firewalled or mirror-only network, vendoring fails (vendor_fetch_failed).
  3. GOMODCACHE / GOPATH set with go env -w → installed modules aren't found. go env GOMODCACHE and go build use the configured cache, but apply crawls $HOME/go/pkg/mod and reports The targeted manifest patch matched no installed package … 1 not found on disk (exit 1; package_not_installed in --json).

Repro (hermetic; example.com/upstream served from a local HTTP "mirror")

# fresh machine: empty cache, settings written the way the Go docs recommend
export GOENV=$T/goenv GOMODCACHE=$T/cold/modcache GOFLAGS= ; unset GOPROXY GOPRIVATE
go env -w GOPROXY=http://127.0.0.1:18702 GOSUMDB=off GOPRIVATE=example.com
socket-patch vendor --ecosystems golang --json
#  "errorCode": "vendor_fetch_failed",
#  "error": "GET https://proxy.golang.org/example.com/upstream/@v/v1.0.0.zip: HTTP 404 Not Found"
#  (the private path left the machine; the local mirror log shows 0 requests)

# control: the same values as real env vars
GOPRIVATE=example.com socket-patch vendor --ecosystems golang --json
#  "reason": "example.com/upstream matches GOPRIVATE, so go fetches it directly, never through a module proxy; not fetching it …"

# GOMODCACHE
go env -w GOMODCACHE=$T/modcache GOPROXY=file://$T/proxy; unset GOMODCACHE
go env GOMODCACHE && go build ./...                # the configured cache, build ok
socket-patch apply --offline --ecosystems golang   # "matched no installed package", exit 1

Expected vs actual

  • Expected: goproxy_base says it returns "the module proxy go itself would ask for module, or Err when go would not use a proxy for it … Falling back to a public proxy there would send a private module path off the machine". The crawler should find the cache go env GOMODCACHE names. Go resolves each variable from the environment first, then from the GOENV file, then defaults.
  • Actual: only std::env::var is consulted, so a go env -w configuration silently falls back to the defaults (proxy.golang.org, $HOME/go/pkg/mod).

Matrix (probe run https://github.com/SocketDev/socket-patch/actions/runs/36746894687, plus local)

OS go GOPRIVATE via go env -w GOMODCACHE via go env -w env-var control
Linux 1.16.15, 1.21.13, 1.24.7 (local), 1.26.3 fail (proxy.golang.org GET) fail pass
macOS 1.24.13, 1.26.3 fail fail pass
Windows 1.16.15, 1.21.13, 1.26.3 fail fail pass

The GOPROXY-mirror bypass was reproduced locally twice on Linux. The GOMODCACHE miss is the same in 4.0.0. In 4.0.0 even the env-var GOPRIVATE control leaks (fixed on main by #252).

Suspect code

  • crates/socket-patch-core/src/vendor/registry_fetch.rs:1270 goproxy_base: std::env::var for SOCKET_GOPROXY, GONOPROXY, GOPRIVATE, GOPROXY only.
  • crates/socket-patch-core/src/crawlers/go_crawler.rs:209 get_gomodcache: GOMODCACHE → GOPATH → $HOME/go from the env only. It needs the GOENV file (or a go env -json fallback when go is on PATH) between env and defaults. Note GOENV=off disables the file.

Backlog review — 2026-10-08

Priority: P2 → P1. Ignoring persisted GOPRIVATE can disclose private module names to a public proxy; also bypasses configured infrastructure.

Activity

  1. mikolalysenko commented on Sep 30, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Triaged: priority:p2 (Go modules). Not a duplicate, and no open or merged PR fixes it. Confirmed on main f6b7fb9: goproxy_base (vendor/registry_fetch.rs) and get_gomodcache (crawlers/go_crawler.rs) read std::env::var only. All three symptoms (GOPRIVATE, GOPROXY and GOMODCACHE) come from one missing piece, a Go-env resolver (env → $GOENV file unless GOENV=off → defaults) used by both call sites, so they belong in one fix. This is a different cause from #343.


    Generated by Claude Code

  2. mikolalysenko commented on Oct 1, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] New information: this also breaks global mode, silently. On main 2463257 (Linux, go 1.24.7, non-root), I ran go env -w GOMODCACHE=$R/custom-cache and then go mod download example.com/upstream@v1.0.0. go env GOMODCACHE points at the custom cache, and the module is there.

    • socket-patch scan -g --json --ecosystems golang → exit 0, "status": "success", scannedPackages: 0. A module with a patch is reported as nothing to patch, with no warning.
    • socket-patch get -g pkg:golang/example.com/upstream@v1.0.0 → exit 1, "matched no installed package" (loud, at least).

    GoCrawler::get_gomodcache (crates/socket-patch-core/src/crawlers/go_crawler.rs:209) reads only the GOMODCACHE / GOPATH / HOME env vars and never the GOENV file, so the report-only global scan misses the user's real cache.


    Generated by Claude Code

  3. added
    v5-blockerMust resolve before v5: public interface/migration or ordinary patch-install-undo failure.
    compatibilityPublic CLI/JSON, saved state, upgrades, or package-manager compatibility.
    and removed on Oct 8, 2026
  4. mikolalysenko commented on Oct 9, 2026

    @mikolalysenko
    CollaboratorAuthor

    v5 release blocker (P1). Honor the Go configuration users set with go env -w; a normal scan must not bypass their proxy/private-module settings.

    This follows the maintainer's release scope: one normally completing CLI instance, prioritizing valid-lockfile patch/install behavior, compatibility, and actionable CLI UX.

  5. mikolalysenko commented on Oct 9, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Claiming for v5 blocker burn-down (shared root cause: Go settings resolved only from process env, never from the GOENV file). Branch: agent/v5-go-env-file. Claim-ID: 2026-10-09T16:41:32Z-3cf085

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:claimedagent:triagedbugSomething isn't workingbughuntFound by a scheduled package-manager bug-hunt agentcompatibilityPublic CLI/JSON, saved state, upgrades, or package-manager compatibility.pm:goGo modulespriority:p1v5-blockerMust resolve before v5: public interface/migration or ordinary patch-install-undo failure.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions