Skip to content

Propagate DIFC proxy TLS CA trust to git/gh/curl via process environment#4042

Merged
lpcox merged 11 commits intomainfrom
copilot/fix-ssl-certificate-error
Apr 17, 2026
Merged

Propagate DIFC proxy TLS CA trust to git/gh/curl via process environment#4042
lpcox merged 11 commits intomainfrom
copilot/fix-ssl-certificate-error

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 17, 2026

gh repo clone / git clone failed through the DIFC TLS proxy (https://localhost:18443/...) because clients could not validate the proxy’s generated certificate chain. This change propagates the generated proxy CA to the toolchains that perform HTTPS validation in agent workflows.

  • Proxy startup: propagate CA trust to common clients

    • On awmg proxy --tls, set process env vars to the generated ca.crt:
      • NODE_EXTRA_CA_CERTS
      • SSL_CERT_FILE
      • GIT_SSL_CAINFO
      • CURL_CA_BUNDLE
      • REQUESTS_CA_BUNDLE
    • This covers gh, git, curl, and other TLS consumers that honor standard CA env settings.
  • No GITHUB_ENV dependency

    • TLS trust propagation no longer reads or writes GITHUB_ENV.
    • Proxy startup relies only on process environment exports for trust configuration.
  • Operator-facing output and docs

    • Proxy connection hints include git-relevant exports (SSL_CERT_FILE, GIT_SSL_CAINFO).
    • docs/PROXY_MODE.md documents CA setup for gh + git without GITHUB_ENV automation.
  • Focused unit coverage

    • Added/updated tests for:
      • env var propagation
      • no reliance on GITHUB_ENV (including asserting the file remains unchanged)
      • rejection of newline-containing CA paths
var tlsTrustEnvKeys = []string{
    "NODE_EXTRA_CA_CERTS",
    "SSL_CERT_FILE",
    "GIT_SSL_CAINFO",
    "CURL_CA_BUNDLE",
    "REQUESTS_CA_BUNDLE",
}

> [!WARNING]
>
>

Copilot AI changed the title [WIP] Fix SSL certificate problem for git clone through DIFC proxy Propagate DIFC proxy TLS CA trust to git/gh/curl via env + GitHub Actions environment file Apr 17, 2026
Copilot AI requested a review from lpcox April 17, 2026 21:34
@lpcox lpcox marked this pull request as ready for review April 17, 2026 22:36
Copilot AI review requested due to automatic review settings April 17, 2026 22:36
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR propagates the DIFC proxy’s generated TLS CA certificate to common HTTPS clients (git/gh/curl/etc) by setting standard CA-related environment variables, including automatic propagation to downstream GitHub Actions steps via GITHUB_ENV.

Changes:

  • Set multiple CA trust env vars (NODE_EXTRA_CA_CERTS, SSL_CERT_FILE, GIT_SSL_CAINFO, CURL_CA_BUNDLE, REQUESTS_CA_BUNDLE) when awmg proxy --tls generates a CA.
  • Append the same env vars to the GitHub Actions environment file (GITHUB_ENV) when present.
  • Add unit tests and update proxy mode documentation with the additional exports.
Show a summary per file
File Description
internal/cmd/proxy.go Adds TLS trust env propagation + best-effort GITHUB_ENV appending and updates connection hints.
internal/cmd/proxy_test.go Adds tests covering env propagation, GITHUB_ENV append behavior, and newline rejection.
docs/PROXY_MODE.md Documents CA env setup for gh+git and notes automatic GITHUB_ENV propagation.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 3/3 changed files
  • Comments generated: 3

Comment thread internal/cmd/proxy.go Outdated
Comment on lines +337 to +348
// Best-effort append: the proxy should still start even if GITHUB_ENV cannot be opened.
f, err := os.OpenFile(githubEnvPath, os.O_APPEND|os.O_WRONLY, 0o644)
if err != nil {
logger.LogWarn("startup", "Skipping GITHUB_ENV TLS trust export: open failed for %s: %v", githubEnvPath, err)
return nil
}
defer f.Close()

for _, key := range tlsTrustEnvKeys {
if _, err := io.WriteString(f, key+"="+caCertPath+"\n"); err != nil {
return fmt.Errorf("failed writing %s to GITHUB_ENV file: %w", key, err)
}
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

configureTLSTrustEnvironment treats opening GITHUB_ENV as best-effort (logs a warning and continues), but write failures currently return an error and will abort proxy startup. This conflicts with the intended/ documented behavior of not failing startup when GITHUB_ENV is unavailable/unwritable. Consider making write failures best-effort too (log a warning and continue/return nil), or at least gate it behind the same best-effort policy as open failures.

Copilot uses AI. Check for mistakes.
Comment thread internal/cmd/proxy.go Outdated
}

// Best-effort append: the proxy should still start even if GITHUB_ENV cannot be opened.
f, err := os.OpenFile(githubEnvPath, os.O_APPEND|os.O_WRONLY, 0o644)
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

os.OpenFile(githubEnvPath, os.O_APPEND|os.O_WRONLY, 0o644) does not use the provided permissions unless os.O_CREATE is set, so 0o644 is effectively ignored here. To avoid implying that permissions are being applied, consider passing 0 (or adding os.O_CREATE if you actually want to create the file when missing).

Suggested change
f, err := os.OpenFile(githubEnvPath, os.O_APPEND|os.O_WRONLY, 0o644)
f, err := os.OpenFile(githubEnvPath, os.O_APPEND|os.O_WRONLY, 0)

Copilot uses AI. Check for mistakes.
Comment thread internal/cmd/proxy_test.go Outdated
}
})

t.Run("skips GITHUB_ENV append when env var is unset", func(t *testing.T) {
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Subtest name says "env var is unset" but the test uses t.Setenv("GITHUB_ENV", ""), which sets it to an empty string rather than truly unsetting it. Since os.Getenv treats unset and empty equivalently this still exercises the code path, but the name is misleading; consider renaming to "unset or empty" (or use os.Unsetenv if you specifically want to test "unset").

Suggested change
t.Run("skips GITHUB_ENV append when env var is unset", func(t *testing.T) {
t.Run("skips GITHUB_ENV append when env var is unset or empty", func(t *testing.T) {

Copilot uses AI. Check for mistakes.
@lpcox
Copy link
Copy Markdown
Collaborator

lpcox commented Apr 17, 2026

@copilot update the pr with review feedback #4042 (review)

@lpcox
Copy link
Copy Markdown
Collaborator

lpcox commented Apr 17, 2026

@copilot don't rely on GITHUB_ENV

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 17, 2026

@copilot update the pr with review feedback #4042 (review)

Implemented the requested review updates in d0e7f64 (and final clarification in 0ed4820). GITHUB_ENV open/write failures are now fully best-effort, the OpenFile mode intent is documented, and the test naming/coverage was updated accordingly.

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 17, 2026

@copilot don't rely on GITHUB_ENV

Updated as requested in d676b90 (with test hardening in a2d0e31): configureTLSTrustEnvironment no longer reads or writes GITHUB_ENV; it only sets the TLS trust vars in process env, and docs/tests were aligned.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • example.com
    • Triggering command: /tmp/go-build4082230878/b510/launcher.test /tmp/go-build4082230878/b510/launcher.test -test.testlogfile=/tmp/go-build4082230878/b510/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true 1.10.2/active_help.go 1.10.2/args.go x_amd64/vet --gdwarf-5 tion -o x_amd64/vet -I g_.a -I x_amd64/vet -g" resolver/delegat-atomic -o x_amd64/vet (dns block)
    • Triggering command: /tmp/go-build492822495/b514/launcher.test /tmp/go-build492822495/b514/launcher.test -test.testlogfile=/tmp/go-build492822495/b514/testlog.txt -test.paniconexit0 -test.timeout=10m0s 9760�� github.com/segmentio/asm/ascii .cfg 64/pkg/tool/linux_amd64/vet -I /tmp/go-build379--norc -I 64/pkg/tool/linux_amd64/vet estl�� GOOS_linux -D 64/pkg/tool/linux_amd64/vet -D GOAMD64_v1 -gensymabis 64/pkg/tool/linux_amd64/vet (dns block)
  • invalid-host-that-does-not-exist-12345.com
    • Triggering command: /tmp/go-build4082230878/b492/config.test /tmp/go-build4082230878/b492/config.test -test.testlogfile=/tmp/go-build4082230878/b492/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true @v1.1.3/cpu/cpu.go 5170394/b151/ x_amd64/vet -p log lcache/go/1.25.8-unreachable=false x_amd64/vet 5170�� 01.o bnTAP0KDS x_amd64/vet --gdwarf-5 --64 -o x_amd64/vet (dns block)
    • Triggering command: /tmp/go-build492822495/b496/config.test /tmp/go-build492822495/b496/config.test -test.testlogfile=/tmp/go-build492822495/b496/testlog.txt -test.paniconexit0 -test.timeout=10m0s (dns block)
  • nonexistent.local
    • Triggering command: /tmp/go-build4082230878/b510/launcher.test /tmp/go-build4082230878/b510/launcher.test -test.testlogfile=/tmp/go-build4082230878/b510/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true 1.10.2/active_help.go 1.10.2/args.go x_amd64/vet --gdwarf-5 tion -o x_amd64/vet -I g_.a -I x_amd64/vet -g" resolver/delegat-atomic -o x_amd64/vet (dns block)
    • Triggering command: /tmp/go-build492822495/b514/launcher.test /tmp/go-build492822495/b514/launcher.test -test.testlogfile=/tmp/go-build492822495/b514/testlog.txt -test.paniconexit0 -test.timeout=10m0s 9760�� github.com/segmentio/asm/ascii .cfg 64/pkg/tool/linux_amd64/vet -I /tmp/go-build379--norc -I 64/pkg/tool/linux_amd64/vet estl�� GOOS_linux -D 64/pkg/tool/linux_amd64/vet -D GOAMD64_v1 -gensymabis 64/pkg/tool/linux_amd64/vet (dns block)
  • slow.example.com
    • Triggering command: /tmp/go-build4082230878/b510/launcher.test /tmp/go-build4082230878/b510/launcher.test -test.testlogfile=/tmp/go-build4082230878/b510/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true 1.10.2/active_help.go 1.10.2/args.go x_amd64/vet --gdwarf-5 tion -o x_amd64/vet -I g_.a -I x_amd64/vet -g" resolver/delegat-atomic -o x_amd64/vet (dns block)
    • Triggering command: /tmp/go-build492822495/b514/launcher.test /tmp/go-build492822495/b514/launcher.test -test.testlogfile=/tmp/go-build492822495/b514/testlog.txt -test.paniconexit0 -test.timeout=10m0s 9760�� github.com/segmentio/asm/ascii .cfg 64/pkg/tool/linux_amd64/vet -I /tmp/go-build379--norc -I 64/pkg/tool/linux_amd64/vet estl�� GOOS_linux -D 64/pkg/tool/linux_amd64/vet -D GOAMD64_v1 -gensymabis 64/pkg/tool/linux_amd64/vet (dns block)
  • this-host-does-not-exist-12345.com
    • Triggering command: /tmp/go-build4082230878/b519/mcp.test /tmp/go-build4082230878/b519/mcp.test -test.testlogfile=/tmp/go-build4082230878/b519/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true g_.a 5170394/b288/ x_amd64/vet -pthread -Wl,--no-gc-sect-atomic -fmessage-length-bool x_amd64/vet 5170�� .cfg elemetry.io/otel-ifaceassert x_amd64/link -p github.com/tetra-o -lang=go1.24 x_amd64/link (dns block)
    • Triggering command: /tmp/go-build492822495/b523/mcp.test /tmp/go-build492822495/b523/mcp.test -test.testlogfile=/tmp/go-build492822495/b523/testlog.txt -test.paniconexit0 -test.timeout=10m0s ortc�� 9760481/b478/_pkg_.a 64/src/internal/fuzz/counters_supported.go 64/pkg/tool/linux_amd64/vet -c=4 b/gh-aw-mcpg/int-test.testlogfile=/tmp/go-build492822495/b505/testlog.txt -importcfg 64/pkg/tool/linu-test.timeout=10m0s (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot AI changed the title Propagate DIFC proxy TLS CA trust to git/gh/curl via env + GitHub Actions environment file Propagate DIFC proxy TLS CA trust to git/gh/curl via process environment Apr 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

DIFC proxy: git clone fails with SSL certificate error through localhost:18443

3 participants