From ca638c5b7e2f90561473e88f4345c6d4e714265f Mon Sep 17 00:00:00 2001 From: Nick Taylor Date: Sun, 25 Jan 2026 05:57:30 +0000 Subject: [PATCH] feat(gateway): update runtime config guard for trusted-proxy - Allow non-loopback bind with trusted-proxy auth mode - Reject trusted-proxy + loopback combination (nonsensical) - Require trustedProxies to be configured for trusted-proxy mode Part of #1560 Co-Authored-By: Claude Sonnet 4.5 --- src/gateway/server-runtime-config.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/gateway/server-runtime-config.ts b/src/gateway/server-runtime-config.ts index a155c5d0a..87f8dbdd7 100644 --- a/src/gateway/server-runtime-config.ts +++ b/src/gateway/server-runtime-config.ts @@ -74,6 +74,8 @@ export async function resolveGatewayRuntimeConfig(params: { const canvasHostEnabled = process.env.CLAWDBOT_SKIP_CANVAS_HOST !== "1" && params.cfg.canvasHost?.enabled !== false; + const trustedProxies = params.cfg.gateway?.trustedProxies ?? []; + assertGatewayAuthConfigured(resolvedAuth); if (tailscaleMode === "funnel" && authMode !== "password") { throw new Error( @@ -89,6 +91,20 @@ export async function resolveGatewayRuntimeConfig(params: { ); } + // Trusted-proxy mode validations + if (authMode === "trusted-proxy") { + if (isLoopbackHost(bindHost)) { + throw new Error( + "gateway auth mode=trusted-proxy makes no sense with bind=loopback; use bind=lan or bind=custom with gateway.trustedProxies configured", + ); + } + if (trustedProxies.length === 0) { + throw new Error( + "gateway auth mode=trusted-proxy requires gateway.trustedProxies to be configured with at least one proxy IP", + ); + } + } + return { bindHost, controlUiEnabled,