From 0e3dc23639053448febf6fab279543edef08f929 Mon Sep 17 00:00:00 2001 From: Mathieu Virbel Date: Wed, 4 Mar 2026 12:40:27 -0600 Subject: [PATCH] fix: set HTTP_PROXY for macOS daemon mode alongside ALL_PROXY ALL_PROXY=socks5h:// only works for SOCKS5-aware apps (curl, git). Apps like opencode that only check HTTP_PROXY/HTTPS_PROXY were not using the proxy at all, causing DNS resolution failures. Now sets both: - ALL_PROXY=socks5h://host:42052 (SOCKS5 with proxy-side DNS) - HTTP_PROXY=http://host:42051 (HTTP CONNECT proxy) The HTTP CONNECT proxy on port 42051 resolves DNS server-side, so apps that don't speak SOCKS5 still get proper DNS resolution through the proxy. --- internal/sandbox/macos.go | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/internal/sandbox/macos.go b/internal/sandbox/macos.go index b5d006e..da93c56 100644 --- a/internal/sandbox/macos.go +++ b/internal/sandbox/macos.go @@ -748,8 +748,11 @@ func WrapCommandMacOS(cfg *config.Config, command string, exposedPorts []int, da // ALL_PROXY=socks5h:// so proxy-aware apps (curl, git, etc.) resolve DNS // through the SOCKS5 proxy. The "h" suffix means "resolve hostname at proxy". // - // We only set ALL_PROXY (not HTTP_PROXY/HTTPS_PROXY) because apps like - // Bun/Node.js read HTTP_PROXY but don't support SOCKS5 protocol. + // Set ALL_PROXY and HTTP_PROXY/HTTPS_PROXY with socks5h:// so both + // SOCKS5-aware apps (curl, git) and HTTP-proxy-aware apps (opencode, + // Node.js tools) resolve DNS through the proxy. The "h" suffix means + // "resolve hostname at proxy side". Note: apps that read HTTP_PROXY + // but don't support SOCKS5 protocol (e.g., Bun) may fail to connect. // // sudo resets the environment, so we use `env` after sudo to re-inject // terminal vars (TERM, COLORTERM, etc.) needed for TUI apps. @@ -758,7 +761,22 @@ func WrapCommandMacOS(cfg *config.Config, command string, exposedPorts []int, da // Convert socks5:// → socks5h:// for hostname resolution through proxy. socks5hURL := strings.Replace(cfg.Network.ProxyURL, "socks5://", "socks5h://", 1) if socks5hURL != "" { - sandboxEnvs = append(sandboxEnvs, "ALL_PROXY="+socks5hURL, "all_proxy="+socks5hURL) + // ALL_PROXY uses socks5h:// (DNS resolved at proxy side) for + // SOCKS5-aware apps (curl, git). + // HTTP_PROXY/HTTPS_PROXY use http:// pointing to the GreyHaven + // HTTP CONNECT proxy (port 42051) for apps that only understand + // HTTP proxies (opencode, Node.js tools, etc.). The CONNECT + // proxy resolves DNS server-side. + proxyHost := "localhost" + if u, err := url.Parse(socks5hURL); err == nil && u.Hostname() != "" { + proxyHost = u.Hostname() + } + httpProxyURL := "http://" + proxyHost + ":42051" + sandboxEnvs = append(sandboxEnvs, + "ALL_PROXY="+socks5hURL, "all_proxy="+socks5hURL, + "HTTP_PROXY="+httpProxyURL, "http_proxy="+httpProxyURL, + "HTTPS_PROXY="+httpProxyURL, "https_proxy="+httpProxyURL, + ) } termEnvs := getTerminalEnvVars() parts = append(parts, "sudo", "-u", uid, "-g", daemonSession.SandboxGroup, "env")