Repository navigation
Description
Summary
The host daemon's own WebSocket connections ignore HTTPS_PROXY / HTTP_PROXY / NO_PROXY, even with NODE_USE_ENV_PROXY=1. On a machine whose only route out is an HTTP CONNECT proxy (no direct egress, often no external DNS), the daemon cannot reach the server: the server WebSocket times out ("Server connection timed out after 60000ms") and the machine never enrolls. The same applies to the bb connect tunnel and the machine auth proxy's upstream requests. I expected the daemon to use the proxy the environment declares, as fetch does under NODE_USE_ENV_PROXY=1.
Versions and environment
- bb
main@17b19716c5a00bf29a6b51798ddb07b72acaf259(bb-app 0.45.0); first seen on 0.43.0 - Linux host daemon (remote machine), Node 24; also reproduced on macOS with Node 25
- Outbound access only through an HTTP CONNECT proxy, exported as
HTTPS_PROXY/HTTP_PROXYwithNO_PROXYfor local ranges
Steps to reproduce
Universal repro, no restricted network needed: point the proxy variables at a dead port. If the proxy were honoured, both requests would fail with ECONNREFUSED.
cd apps/host-daemon # uses the daemon's own ws dependency (ws 8.21.0)
cat > /tmp/ws-proxy-repro.mjs <<'JS'
import { createRequire } from "node:module";
const require = createRequire(process.cwd() + "/package.json");
const { WebSocket } = require("ws");
const fetchResult = await fetch("https://example.com", { signal: AbortSignal.timeout(10000) })
.then((r) => `status ${r.status}`, (e) => `ERR ${e.cause?.code ?? e.message}`);
console.log("fetch:", fetchResult);
const ws = new WebSocket("wss://ws.postman-echo.com/raw");
ws.on("open", () => { console.log("ws: open (direct connection, proxy ignored)"); ws.close(); });
ws.on("error", (e) => console.log("ws: ERR", e.code ?? e.message));
JS
HTTPS_PROXY=http://127.0.0.1:1 HTTP_PROXY=http://127.0.0.1:1 NODE_USE_ENV_PROXY=1 node /tmp/ws-proxy-repro.mjsOn a proxy-only machine: install a host daemon with the proxy variables set; it never enrolls.
Expected vs actual
fetch: ERR ECONNREFUSED
ws: open (direct connection, proxy ignored)
Expected: ws fails the same way (or, with a working proxy, tunnels through it). Actual: ws dials its own socket and ignores the proxy, because it only uses a proxy when given an agent.
Evidence
The three daemon dial sites construct sockets without an agent:
- server WebSocket:
super(address, protocols, { headers }); - bb connect tunnel:
new NodeWebSocket(url, { headers: websocketOptions.headers })); - machine auth proxy upstream:
bb/apps/host-daemon/src/machine-auth-proxy.ts
Line 115 in 17b1971
return requestFn({
What you ruled out
- Not bb's own outbound fetch() ignores HTTP_PROXY/HTTPS_PROXY: provider usage and Codex subscription calls fail (HTTP 403) behind a mandatory proxy #3239: that issue is about bb's own
fetchcalls on the server and in provider plugins, whichNODE_USE_ENV_PROXY=1(or an undici dispatcher) fixes. These daemon paths usewsandnode:http(s)with their own sockets, which neither covers; the repro above setsNODE_USE_ENV_PROXY=1andwsstill connects directly. https-proxy-agentis in the lockfile as a transitive dependency, but it has noNO_PROXYhandling.
Proposed fix (prototype)
A fork branch, rebased on the commit above: RIMTHAN-LAB@90bc852 (branch host-daemon-env-proxy).
apps/host-daemon/src/env-proxy-agent.ts:proxyAgentFor(url, env)returns a small CONNECT-tunnel agent (http and https proxies, BasicProxy-Authorizationfrom the proxy URL's userinfo, TLS to the target layered over the tunnel) orundefinedfor a direct connection.NO_PROXYfollows curl's rules (*, host,.suffix,*.suffix,host:port, bracketed IPv6) plus CIDR ranges. Loopback targets always connect directly, so local server/daemon traffic is never sent to a proxy (the concern raised in bb's own outbound fetch() ignores HTTP_PROXY/HTTPS_PROXY: provider usage and Codex subscription calls fail (HTTP 403) behind a mandatory proxy #3239).- The three dial sites resolve the agent at dial time. With no proxy set, behaviour is unchanged.
- No wire change, so no
HOST_DAEMON_PROTOCOL_VERSIONbump.docs/configuration.mddocuments the variables. - Tests (
src/env-proxy-agent.test.ts) run a local CONNECT proxy and local ws/wss servers: a proxied connection reaches a host only the proxy can resolve, wss keeps TLS end to end, no proxy andNO_PROXYconnect directly, loopback bypasses the proxy, and a refused tunnel fails without echoing credentials. Two of them fail onmainand pass with the change.vitestforenv-proxy-agent,machine-auth-proxy,connect-tunnelandserver-connectionpasses (48 tests), host-daemontscreports no errors in its sources, and oxlint/oxfmt are clean on the touched files.
I'd be glad to open this as a PR once a maintainer approves it.
Suggested priority and effort
Medium: it blocks every daemon on a proxy-only network and there is no workaround short of a transparent proxy. Effort is low; the prototype is self-contained in apps/host-daemon.
AGENT GENERATED
Activity
bb-slop-cop commentedon Oct 5, 2026
🚨 SLOP COP 🚨 ·
new-issue-autopilothost,connect.createConnection; without an explicit agent, Node skips its environment-aware global agent and resolves the destination directly. All four ws/wss variants fail the focused routing regression; 38 relevant existing tests pass.confirmed-repro. Correction: machine-auth HTTP upstream requests already honor the proxy on Node 24.5.0 with native proxy opt-in.One host toolchain for executable discovery, child PATH, and proxy/CA…