-
-
Notifications
You must be signed in to change notification settings - Fork 69.5k
[Bug]: Control UI fails to authenticate over plain HTTP (insecure context) #44864
Description
Bug type
Behavior bug (incorrect output/state without crash)
Summary
The Control UI's GatewayBrowserClient does not send token or password credentials in the WebSocket connect frame when accessed over plain HTTP, causing the gateway to reject the connection with CONTROL_UI_DEVICE_IDENTITY_REQUIRED even when gateway.controlUi.dangerouslyDisableDeviceAuth is enabled.
Steps to reproduce
- Run a gateway on a LAN host (e.g.
192.168.1.x) withgateway.controlUi.dangerouslyDisableDeviceAuth: true - Reverse-proxy the gateway behind a plain HTTP server (no TLS)
- Open the Control UI in a browser via
http://host/gateway/#token=<valid-token> - Observe the connection fails with "device identity required"
Expected behavior
The Control UI should connect successfully using the provided token, falling back to token-only auth when crypto.subtle is unavailable (as it is in non-secure browser contexts).
Actual behavior
The connect frame is sent with auth: undefined because selectConnectAuth() is only called inside the if (isSecureContext) block. The explicit token and password from the login form / URL hash are never included in the connect frame. The gateway sees no credentials, so sharedAuthOk is false and roleCanSkipDeviceIdentity() returns false, resulting in rejection.
OpenClaw version
v2026.3.12
Operating system
Linux (Debian 12, Docker container) — affects any OS when accessed over plain HTTP
Install method
Docker
Model
N/A (gateway connection issue, not model-specific)
Provider / routing chain
N/A
Logs, screenshots, and evidence
Gateway close: code=4008, reason="connect failed"
Error detail code: CONTROL_UI_DEVICE_IDENTITY_REQUIRED
Impact and severity
- Affected: Any deployment accessing the Control UI over plain HTTP (common in LAN/Docker setups behind a reverse proxy without TLS)
- Severity: High — Control UI is completely non-functional
- Frequency: 100% repro on any non-HTTPS connection
- Consequence: Operators cannot use the built-in Control UI for administration
Additional information
The root cause is in ui/src/ui/gateway.ts in the sendConnect() method. The selectConnectAuth() call (which resolves cached device tokens and explicit credentials) is gated behind if (isSecureContext), but the fallback outside that block does not use the explicit token/password from this.opts.token and this.opts.password. This means in insecure contexts, selectedAuth remains { canFallbackToShared: false } and no auth fields propagate to the connect frame.
Reported by Claude Code (Opus 4.6). Reviewed and tested by @asyncjason.