From 62c944f651ca3943f534ce8e06c1993656b6a3fb Mon Sep 17 00:00:00 2001 From: jketema <93738568+jketema@users.noreply.github.com> Date: Thu, 22 Oct 2026 14:17:37 +0000 Subject: [PATCH] Go: Pass proxy certificate to git via `GIT_SSL_CAINFO` The extractor ran `git config --global http.sslCAInfo ` when private `git_source` registries were configured. That permanently modified the user's global git configuration, and on non-ephemeral (e.g. self-hosted) runners it kept pointing at a temporary certificate file after the job finished, breaking later git HTTPS operations. Instead, set `GIT_SSL_CAINFO` alongside `SSL_CERT_FILE` in the environment that `ApplyProxyEnvVars` applies to `go` commands. This is picked up by the `git` processes `go` spawns, and is scoped to those subprocesses. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- go/extractor/registries/registryproxy.go | 21 +++++++----------- go/extractor/registries/registryproxy_test.go | 22 +++++++++++++++++++ 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/go/extractor/registries/registryproxy.go b/go/extractor/registries/registryproxy.go index 39578af476be..0875e6b7aa60 100644 --- a/go/extractor/registries/registryproxy.go +++ b/go/extractor/registries/registryproxy.go @@ -103,7 +103,14 @@ func getEnvVars() []string { slog.Error("Failed to close the temporary certificate file", slog.String("error", err.Error())) } else { proxy_cert_file = f.Name() - result = append(result, fmt.Sprintf("SSL_CERT_FILE=%s", proxy_cert_file)) + // `SSL_CERT_FILE` is used by Go itself; `GIT_SSL_CAINFO` is used by the `git` + // processes that `go` spawns to fetch `git_source` modules. Setting it here scopes + // the certificate to our subprocesses instead of modifying the global git configuration. + result = append( + result, + fmt.Sprintf("SSL_CERT_FILE=%s", proxy_cert_file), + fmt.Sprintf("GIT_SSL_CAINFO=%s", proxy_cert_file), + ) } } @@ -160,18 +167,6 @@ func getEnvVars() []string { if len(git_sources) > 0 { goprivate = append(goprivate, git_sources...) - - if proxy_cert_file != "" { - slog.Info("Configuring `git` to use proxy certificate", slog.String("path", proxy_cert_file)) - cmd := exec.Command("git", "config", "--global", "http.sslCAInfo", proxy_cert_file) - - out, cmdErr := cmd.CombinedOutput() - slog.Info(string(out)) - - if cmdErr != nil { - slog.Error("Failed to configure `git` to accept the certificate file", slog.String("error", cmdErr.Error())) - } - } } result = append(result, fmt.Sprintf("GOPRIVATE=%s", strings.Join(goprivate, ","))) diff --git a/go/extractor/registries/registryproxy_test.go b/go/extractor/registries/registryproxy_test.go index 2f0b34bcb036..bd5d305747a4 100644 --- a/go/extractor/registries/registryproxy_test.go +++ b/go/extractor/registries/registryproxy_test.go @@ -1,6 +1,8 @@ package registries import ( + "os" + "slices" "testing" ) @@ -131,3 +133,23 @@ func TestParseRegistryConfigsMultipleGoProxyServers(t *testing.T) { t.Fatalf("Expected `URL` to be `https://goproxy.io`, but got `%s`", second.URL) } } + +func TestGetEnvVarsScopesCertificateToSubprocesses(t *testing.T) { + t.Setenv(PROXY_HOST, "") + t.Setenv(PROXY_PORT, "") + t.Setenv(PROXY_URLS, "") + t.Setenv(PROXY_CA_CERTIFICATE, "dummy certificate") + + vars := getEnvVars() + defer os.Remove(proxy_cert_file) + + if proxy_cert_file == "" { + t.Fatal("Expected a temporary certificate file to be created.") + } + + for _, expected := range []string{"SSL_CERT_FILE=" + proxy_cert_file, "GIT_SSL_CAINFO=" + proxy_cert_file} { + if !slices.Contains(vars, expected) { + t.Errorf("Expected `getEnvVars` to return %q, but got %v.", expected, vars) + } + } +}