Skip to content

[Bug]: Control UI fails to authenticate over plain HTTP (insecure context) #44864

@asyncjason

Description

@asyncjason

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

  1. Run a gateway on a LAN host (e.g. 192.168.1.x) with gateway.controlUi.dangerouslyDisableDeviceAuth: true
  2. Reverse-proxy the gateway behind a plain HTTP server (no TLS)
  3. Open the Control UI in a browser via http://host/gateway/#token=<valid-token>
  4. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions