Summary
authorizeGatewayConnect in src/gateway/auth.ts treats trusted-proxy as a single-mode gate. When proxy auth fails (i.e. the request didn't come from a trusted proxy), the function early-returns with a failure before reaching the shared-secret (token/password) or Tailscale authentication paths. This means all internal consumers that connect directly — without going through the reverse proxy — are unable to authenticate.
Affected internal consumers include: node host, CLI RPC, ACP (Agent Client Protocol), TUI, Discord/Telegram/Slack bridges, status probes, mobile apps, and agent tool calls (cron, sessions, system commands).
This was discovered during investigation of #17270.
Steps to reproduce
- Configure gateway with
auth.mode: "trusted-proxy" and a auth.token or auth.password
- Set up a reverse proxy (e.g. Nginx, Caddy, Authelia) that injects the configured
userHeader
- Start gateway — browser connections via the reverse proxy work fine
- Observe that node host, CLI, and other internal services fail to connect
Expected behavior
Internal services that provide a valid token or password should authenticate successfully, even when the gateway is in trusted-proxy mode. The trusted-proxy check should be the primary auth method, with shared-secret (token/password) as a fallback for direct connections.
Actual behavior
All direct connections fail with the proxy auth failure reason (e.g. trusted_proxy_untrusted_source). The token/password credentials are never checked because the trusted-proxy block early-returns before those code paths.
The relevant code path in authorizeGatewayConnect (src/gateway/auth.ts):
if (auth.mode === "trusted-proxy") {
// ... proxy auth check ...
if ("user" in result) {
return { ok: true, method: "trusted-proxy", user: result.user };
}
// ❌ Early return — never reaches token/password/tailscale paths below
return { ok: false, reason: result.reason };
}
// These paths are never reached when mode=trusted-proxy:
// - Rate limiter setup
// - Tailscale auth
// - Token auth
// - Password auth
Additionally, resolveGatewayAuth excludes trusted-proxy from the allowTailscale default:
const allowTailscale =
authConfig.allowTailscale ?? (params.tailscaleMode === "serve" && mode !== "password");
This doesn't explicitly exclude trusted-proxy, but the Tailscale check happens after the trusted-proxy block, so it's unreachable anyway.
OpenClaw version
All versions since trusted-proxy mode was introduced (#1560).
Operating system
All platforms.
Install method
All install methods.
Impact and severity
High — any deployment using trusted-proxy mode has all internal services broken. This includes:
| Consumer |
Impact |
| Node host |
Cannot connect → nodes offline |
| CLI RPC |
Cannot authenticate → CLI non-functional |
| ACP |
Cannot connect → agent tools degraded |
| TUI |
Cannot authenticate |
| Agent tool calls |
Cron, sessions, system commands all fail |
| Bridges (Discord, Telegram, etc.) |
Cannot connect if running externally |
| Status probes |
Health checks fail |
Users may not notice immediately because browser connections through the reverse proxy continue to work.
Additional information
Related issues:
Fix: #17746 adds an inline shared-secret fallback within the trusted-proxy block — when proxy auth fails and a token/password is configured, it attempts shared-secret auth (with rate limiting) before returning failure.
Summary
authorizeGatewayConnectinsrc/gateway/auth.tstreatstrusted-proxyas a single-mode gate. When proxy auth fails (i.e. the request didn't come from a trusted proxy), the function early-returns with a failure before reaching the shared-secret (token/password) or Tailscale authentication paths. This means all internal consumers that connect directly — without going through the reverse proxy — are unable to authenticate.Affected internal consumers include: node host, CLI RPC, ACP (Agent Client Protocol), TUI, Discord/Telegram/Slack bridges, status probes, mobile apps, and agent tool calls (cron, sessions, system commands).
This was discovered during investigation of #17270.
Steps to reproduce
auth.mode: "trusted-proxy"and aauth.tokenorauth.passworduserHeaderExpected behavior
Internal services that provide a valid token or password should authenticate successfully, even when the gateway is in
trusted-proxymode. Thetrusted-proxycheck should be the primary auth method, with shared-secret (token/password) as a fallback for direct connections.Actual behavior
All direct connections fail with the proxy auth failure reason (e.g.
trusted_proxy_untrusted_source). The token/password credentials are never checked because the trusted-proxy block early-returns before those code paths.The relevant code path in
authorizeGatewayConnect(src/gateway/auth.ts):Additionally,
resolveGatewayAuthexcludestrusted-proxyfrom theallowTailscaledefault:This doesn't explicitly exclude
trusted-proxy, but the Tailscale check happens after the trusted-proxy block, so it's unreachable anyway.OpenClaw version
All versions since trusted-proxy mode was introduced (#1560).
Operating system
All platforms.
Install method
All install methods.
Impact and severity
High — any deployment using
trusted-proxymode has all internal services broken. This includes:Users may not notice immediately because browser connections through the reverse proxy continue to work.
Additional information
Related issues:
canSkipDevice/skipPairinggate logicopenclaw node runfails silently with "1008: pairing required" when connecting to a remote gateway #4833 — GatewayClient reconnect behavior (infinite retry with no circuit breaker)Fix: #17746 adds an inline shared-secret fallback within the trusted-proxy block — when proxy auth fails and a token/password is configured, it attempts shared-secret auth (with rate limiting) before returning failure.