From 3aaed98ac0a2b45923030f6316714449ac38b5da Mon Sep 17 00:00:00 2001 From: root Date: Fri, 6 Mar 2026 08:16:43 +0200 Subject: [PATCH] feat(addon): make lan_https device auth toggle configurable Fixes #87 --- DOCS.md | 3 +- openclaw_assistant/CHANGELOG.md | 13 ++++++++ openclaw_assistant/config.yaml | 6 ++++ openclaw_assistant/landing.html.tpl | 2 +- openclaw_assistant/oc_config_helper.py | 35 ++++++++++++---------- openclaw_assistant/run.sh | 3 +- openclaw_assistant/translations/bg.yaml | 4 +++ openclaw_assistant/translations/de.yaml | 4 +++ openclaw_assistant/translations/en.yaml | 4 +++ openclaw_assistant/translations/es.yaml | 4 +++ openclaw_assistant/translations/pl.yaml | 4 +++ openclaw_assistant/translations/pt-BR.yaml | 4 +++ 12 files changed, 68 insertions(+), 18 deletions(-) diff --git a/DOCS.md b/DOCS.md index 885c46d..30e3b63 100644 --- a/DOCS.md +++ b/DOCS.md @@ -275,6 +275,7 @@ All options are set via **Settings → Apps/Add-ons → OpenClaw Assistant → C | `gateway_auth_mode` | `token` / `trusted-proxy` | `token` | Gateway auth mode. Use `trusted-proxy` when terminating HTTPS in a reverse proxy and forwarding trusted auth headers. | | `gateway_trusted_proxies` | string | _(empty)_ | Comma-separated trusted proxy IP/CIDR list used with `gateway_auth_mode: trusted-proxy`. | | `gateway_additional_allowed_origins` | string | _(empty)_ | Comma-separated additional origins merged into `gateway.controlUi.allowedOrigins` in `lan_https` mode (example: `https://ha.example.com:8443,capacitor://localhost`). | +| `controlui_disable_device_auth` | bool | `true` | Controls `gateway.controlUi.dangerouslyDisableDeviceAuth` in `lan_https` mode. **ON (recommended):** skip per-device pairing approval, avoid error 1008 on LAN HTTPS, token auth still required. **OFF:** enforce per-device pairing prompts (stricter, but more friction). | | `force_ipv4_dns` | bool | `true` | Force IPv4-first DNS ordering for Node network calls. **Recommended ON** — most HAOS VMs lack IPv6 egress, causing `web_fetch` and Telegram timeouts. Set to `false` only if your network has working IPv6. | | `gateway_env_vars` | list of `{name, value}` | `[]` | Environment variables exported to the gateway process at startup. UI format: list entries with `name` and `value` (example: `name=OPENAI_API_KEY`, `value=sk-...`). Limits: max 50 vars, key length 255, value length 10000. Reserved runtime keys are blocked (for example `PATH`, `HOME`, `NODE_OPTIONS`, `NODE_PATH`, `OPENCLAW_*`, proxy vars). Legacy string/object formats are still accepted for backward compatibility. | | `nginx_log_level` | `full` / `minimal` | `minimal` | Nginx access log verbosity. `minimal` suppresses repetitive Home Assistant health-check and polling requests (`GET /`, `GET /v1/models`). `full` logs everything. | @@ -779,7 +780,7 @@ Go to **Settings → Add-ons → OpenClaw Assistant → Log** tab. Logs show sta **Cause**: OpenClaw v2026.2.21+ requires new devices to complete a pairing handshake before the Control UI WebSocket is accepted. Loopback connections are auto-approved (v2026.2.22 further improves this with loopback scope-upgrade auto-approval), but LAN connections (including those through the HTTPS proxy) require explicit approval. -**Fix**: In **v0.5.50+** the add-on automatically sets `gateway.controlUi.dangerouslyDisableDeviceAuth: true` on startup when using `lan_https` mode. This bypasses per-device pairing — token authentication is still enforced. +**Fix**: In **v0.5.50+** the add-on configures `gateway.controlUi.dangerouslyDisableDeviceAuth` in `lan_https` mode. By default it is enabled (`controlui_disable_device_auth: true`) to bypass per-device pairing while still enforcing token auth. If you prefer stricter behavior, set `controlui_disable_device_auth: false` and approve new devices manually. > **v2026.2.22 note:** The gateway now logs a security warning on startup when this flag is active. The warning is expected and harmless — run `openclaw security audit` for details. diff --git a/openclaw_assistant/CHANGELOG.md b/openclaw_assistant/CHANGELOG.md index 66280d7..5c6e88a 100644 --- a/openclaw_assistant/CHANGELOG.md +++ b/openclaw_assistant/CHANGELOG.md @@ -2,6 +2,19 @@ All notable changes to the OpenClaw Assistant Home Assistant Add-on will be documented in this file. +## [Unreleased] + +### Added +- New add-on option `controlui_disable_device_auth` (default: `true`) to control whether `gateway.controlUi.dangerouslyDisableDeviceAuth` is enabled in `lan_https` mode. + +### Changed +- `set-control-ui-origins` helper now accepts an explicit device-auth toggle and applies `dangerouslyDisableDeviceAuth` accordingly instead of forcing it on. +- `run.sh` now forwards the add-on option to the config helper. +- Control UI guidance text and docs were updated to explain when device-pairing bypass should be ON vs OFF. + +### Translations +- Added `controlui_disable_device_auth` labels/descriptions to: `en`, `bg`, `de`, `es`, `pl`, `pt-BR`. + ## [0.5.54] - 2026-02-25 ### Changed diff --git a/openclaw_assistant/config.yaml b/openclaw_assistant/config.yaml index 8b66f5c..5705e52 100644 --- a/openclaw_assistant/config.yaml +++ b/openclaw_assistant/config.yaml @@ -100,6 +100,11 @@ options: # Example: "https://ha.example.com:8443,capacitor://localhost" gateway_additional_allowed_origins: "" + # In lan_https mode, disable per-device Control UI auth ceremony. + # Default true (recommended) to avoid interactive pairing error 1008 on LAN. + # Set false only if you explicitly want strict per-device approvals. + controlui_disable_device_auth: true + # Enable OpenAI-compatible Chat Completions API endpoint # When enabled, OpenClaw can be used as a conversation agent in HA Assist pipeline # via Extended OpenAI Conversation (HACS) or any OpenAI-compatible client @@ -151,6 +156,7 @@ schema: gateway_auth_mode: list(token|trusted-proxy)? gateway_trusted_proxies: str? gateway_additional_allowed_origins: str? + controlui_disable_device_auth: bool? enable_openai_api: bool? force_ipv4_dns: bool? gateway_env_vars: diff --git a/openclaw_assistant/landing.html.tpl b/openclaw_assistant/landing.html.tpl index f04a4e5..696eacb 100644 --- a/openclaw_assistant/landing.html.tpl +++ b/openclaw_assistant/landing.html.tpl @@ -211,7 +211,7 @@ SSL tab: Request a new SSL certificate (Let's Encrypt or custom) 'pairing required': { friendly: 'The Gateway requires device pairing before the Control UI can connect.', fix: ACCESS_MODE === 'lan_https' - ? 'Restart the add-on — it auto-sets controlUi.dangerouslyDisableDeviceAuth: true to skip pairing (token auth is still enforced).
Note: v2026.2.22+ shows an expected security warning for this flag in the gateway logs — it is safe to ignore.' + ? 'Restart the add-on — by default it sets controlUi.dangerouslyDisableDeviceAuth: true to skip pairing (token auth is still enforced). You can change this via controlui_disable_device_auth in add-on options.
Note: v2026.2.22+ shows an expected security warning for this flag in the gateway logs — it is safe to ignore.' : 'Set access_mode to lan_https and restart. Or from the terminal: edit /config/.openclaw/openclaw.json and set gateway.controlUi.dangerouslyDisableDeviceAuth: true, then restart the gateway.' }, 'origin not allowed': { diff --git a/openclaw_assistant/oc_config_helper.py b/openclaw_assistant/oc_config_helper.py index 5aea55f..5dcb912 100644 --- a/openclaw_assistant/oc_config_helper.py +++ b/openclaw_assistant/oc_config_helper.py @@ -181,17 +181,16 @@ def apply_gateway_settings(mode: str, remote_url: str, bind_mode: str, port: int return True -def set_control_ui_origins(origins_csv: str, additional_origins_csv: str = ""): +def set_control_ui_origins(origins_csv: str, additional_origins_csv: str = "", disable_device_auth: bool = True): """ Configure gateway.controlUi for the built-in HTTPS proxy. Sets: - allowedOrigins: the HTTPS proxy origins so the browser WebSocket is accepted (required since v2026.2.21). - - dangerouslyDisableDeviceAuth: true — skips the interactive device - pairing ceremony. In a self-hosted HA add-on the user already - controls the gateway token, so the pairing step adds friction - without meaningful security benefit. + - dangerouslyDisableDeviceAuth: controlled by add-on option + `controlui_disable_device_auth` (default true). When true, skips + interactive device pairing; token auth remains enforced. Also removes any stale/invalid keys (e.g. pairingMode) that may have been written by earlier add-on versions. @@ -231,11 +230,13 @@ def set_control_ui_origins(origins_csv: str, additional_origins_csv: str = ""): changes.append(f"allowedOrigins: {current_origins} -> {merged_origins}") # --- dangerouslyDisableDeviceAuth --- - # Skips the interactive pairing handshake (error 1008: pairing required). - # Token auth is still enforced; this only disables the per-device approval. - if control_ui.get("dangerouslyDisableDeviceAuth") is not True: - control_ui["dangerouslyDisableDeviceAuth"] = True - changes.append("dangerouslyDisableDeviceAuth: True") + # Optional bypass of interactive per-device pairing (error 1008: pairing required). + # Token auth is still enforced; this only controls the approval ceremony. + desired_device_auth_flag = True if disable_device_auth else False + if control_ui.get("dangerouslyDisableDeviceAuth") is not desired_device_auth_flag: + prev = control_ui.get("dangerouslyDisableDeviceAuth") + control_ui["dangerouslyDisableDeviceAuth"] = desired_device_auth_flag + changes.append(f"dangerouslyDisableDeviceAuth: {prev} -> {desired_device_auth_flag}") # --- Remove invalid keys from earlier add-on versions --- for stale_key in ("pairingMode",): @@ -244,7 +245,8 @@ def set_control_ui_origins(origins_csv: str, additional_origins_csv: str = ""): changes.append(f"removed invalid key: {stale_key}") if not changes: - print(f"INFO: controlUi already correct: origins={merged_origins}, deviceAuth=disabled") + status = "disabled" if desired_device_auth_flag else "enabled" + print(f"INFO: controlUi already correct: origins={merged_origins}, deviceAuth={status}") return True if write_config(cfg): @@ -287,12 +289,15 @@ def main(): sys.exit(0) elif cmd == "set-control-ui-origins": - if len(sys.argv) not in (3, 4): - print("Usage: oc_config_helper.py set-control-ui-origins [additional_origins_csv]") + if len(sys.argv) not in (3, 4, 5): + print("Usage: oc_config_helper.py set-control-ui-origins [additional_origins_csv] [disable_device_auth:true|false]") sys.exit(1) origins_csv = sys.argv[2] - additional_origins_csv = sys.argv[3] if len(sys.argv) == 4 else "" - success = set_control_ui_origins(origins_csv, additional_origins_csv) + additional_origins_csv = sys.argv[3] if len(sys.argv) >= 4 else "" + disable_device_auth = True + if len(sys.argv) == 5: + disable_device_auth = sys.argv[4].strip().lower() == "true" + success = set_control_ui_origins(origins_csv, additional_origins_csv, disable_device_auth) sys.exit(0 if success else 1) elif cmd == "set": diff --git a/openclaw_assistant/run.sh b/openclaw_assistant/run.sh index 93edeb8..936a1c9 100644 --- a/openclaw_assistant/run.sh +++ b/openclaw_assistant/run.sh @@ -54,6 +54,7 @@ ENABLE_OPENAI_API=$(jq -r '.enable_openai_api // false' "$OPTIONS_FILE") GATEWAY_AUTH_MODE=$(jq -r '.gateway_auth_mode // "token"' "$OPTIONS_FILE") GATEWAY_TRUSTED_PROXIES=$(jq -r '.gateway_trusted_proxies // empty' "$OPTIONS_FILE") GATEWAY_ADDITIONAL_ALLOWED_ORIGINS=$(jq -r '.gateway_additional_allowed_origins // empty' "$OPTIONS_FILE") +CONTROLUI_DISABLE_DEVICE_AUTH=$(jq -r '.controlui_disable_device_auth // true' "$OPTIONS_FILE") FORCE_IPV4_DNS=$(jq -r '.force_ipv4_dns // true' "$OPTIONS_FILE") ACCESS_MODE=$(jq -r '.access_mode // "custom"' "$OPTIONS_FILE") NGINX_LOG_LEVEL=$(jq -r '.nginx_log_level // "minimal"' "$OPTIONS_FILE") @@ -681,7 +682,7 @@ PY fi fi - python3 "$HELPER_PATH" set-control-ui-origins "$ALLOWED_ORIGINS" "$GATEWAY_ADDITIONAL_ALLOWED_ORIGINS" || \ + python3 "$HELPER_PATH" set-control-ui-origins "$ALLOWED_ORIGINS" "$GATEWAY_ADDITIONAL_ALLOWED_ORIGINS" "$CONTROLUI_DISABLE_DEVICE_AUTH" || \ echo "WARN: Could not set controlUi settings — gateway may reject the Control UI" fi diff --git a/openclaw_assistant/translations/bg.yaml b/openclaw_assistant/translations/bg.yaml index ec05aad..9f6d555 100644 --- a/openclaw_assistant/translations/bg.yaml +++ b/openclaw_assistant/translations/bg.yaml @@ -58,6 +58,10 @@ configuration: name: Допълнителни разрешени origins description: Допълнителни origins за Control UI, разделени със запетая; сливат се в gateway.controlUi.allowedOrigins при lan_https (пример - https://ha.example.com:8443,capacitor://localhost) + controlui_disable_device_auth: + name: Изключи device pairing за Control UI (lan_https) + description: "Когато е ВКЛ. (препоръчително), задава gateway.controlUi.dangerouslyDisableDeviceAuth=true и пропуска одобрението по устройство, за да избегне error 1008 в LAN HTTPS режим. Остави ВКЛ. за домашна/доверена мрежа. Изключи само ако искаш стриктно pairing потвърждение за всеки нов браузър/устройство." + gateway_bind_mode: name: Режим на свързване на Gateway description: Режим на мрежово свързване - loopback (само 127.0.0.1, най-сигурен), lan (всички интерфейси) или tailnet (само Tailscale интерфейс). Пренебрегва се от предварителните режими на достъп. diff --git a/openclaw_assistant/translations/de.yaml b/openclaw_assistant/translations/de.yaml index b20f1a2..770dae2 100644 --- a/openclaw_assistant/translations/de.yaml +++ b/openclaw_assistant/translations/de.yaml @@ -58,6 +58,10 @@ configuration: name: Zusätzliche erlaubte Origins description: Kommagetrennte zusätzliche Control-UI-Origins, die bei lan_https in gateway.controlUi.allowedOrigins zusammengeführt werden (Beispiel - https://ha.example.com:8443,capacitor://localhost) + controlui_disable_device_auth: + name: Control-UI-Geräte-Pairing deaktivieren (lan_https) + description: "Wenn EIN (empfohlen), setzt dies gateway.controlUi.dangerouslyDisableDeviceAuth=true, überspringt die Gerätefreigabe und vermeidet Fehler 1008 im LAN-HTTPS-Modus. Für Heim-/vertrauenswürdiges LAN eingeschaltet lassen. Nur AUS schalten, wenn du striktes Geräte-Pairing für jeden neuen Browser/jedes neue Gerät willst." + gateway_bind_mode: name: Gateway-Bindungsmodus description: Netzwerk-Bindungsmodus - loopback (nur 127.0.0.1, am sichersten), lan (alle Schnittstellen) oder tailnet (nur Tailscale-Schnittstelle). Wird durch Zugriffsmodus-Voreinstellungen überschrieben. diff --git a/openclaw_assistant/translations/en.yaml b/openclaw_assistant/translations/en.yaml index 08b00ac..5a4e934 100644 --- a/openclaw_assistant/translations/en.yaml +++ b/openclaw_assistant/translations/en.yaml @@ -58,6 +58,10 @@ configuration: name: Additional Allowed Origins description: Comma-separated extra Control UI origins to merge into gateway.controlUi.allowedOrigins in lan_https mode (example - https://ha.example.com:8443,capacitor://localhost) + controlui_disable_device_auth: + name: Disable Control UI Device Pairing (lan_https) + description: "When ON (recommended), sets gateway.controlUi.dangerouslyDisableDeviceAuth=true to skip per-device approval and avoid error 1008 in LAN HTTPS mode. Keep ON for home/trusted LAN. Turn OFF only when you want strict per-device pairing prompts on every new browser/device." + gateway_bind_mode: name: Gateway Bind Mode description: Network bind mode - loopback (127.0.0.1 only, most secure), lan (all interfaces), or tailnet (Tailscale interface only). Overridden by access_mode presets. diff --git a/openclaw_assistant/translations/es.yaml b/openclaw_assistant/translations/es.yaml index 9a1bf55..9b78c30 100644 --- a/openclaw_assistant/translations/es.yaml +++ b/openclaw_assistant/translations/es.yaml @@ -58,6 +58,10 @@ configuration: name: Orígenes permitidos adicionales description: Orígenes extra de Control UI separados por comas que se combinan en gateway.controlUi.allowedOrigins en modo lan_https (ejemplo - https://ha.example.com:8443,capacitor://localhost) + controlui_disable_device_auth: + name: Desactivar emparejamiento por dispositivo en Control UI (lan_https) + description: "Cuando está ACTIVADO (recomendado), establece gateway.controlUi.dangerouslyDisableDeviceAuth=true para omitir la aprobación por dispositivo y evitar el error 1008 en modo LAN HTTPS. Déjalo ACTIVADO en redes domésticas/de confianza. Desactívalo solo si quieres emparejamiento estricto para cada navegador/dispositivo nuevo." + gateway_bind_mode: name: Modo de enlace del Gateway description: "Modo de enlace de red: loopback (solo 127.0.0.1, más seguro), lan (todas las interfaces) o tailnet (solo interfaz Tailscale). Se anula con las preselecciones del modo de acceso." diff --git a/openclaw_assistant/translations/pl.yaml b/openclaw_assistant/translations/pl.yaml index e0310ff..af9d0ee 100644 --- a/openclaw_assistant/translations/pl.yaml +++ b/openclaw_assistant/translations/pl.yaml @@ -51,6 +51,10 @@ configuration: name: Dodatkowe dozwolone origins description: Dodatkowe origins Control UI rozdzielone przecinkami; łączone z gateway.controlUi.allowedOrigins w trybie lan_https (przykład - https://ha.example.com:8443,capacitor://localhost) + controlui_disable_device_auth: + name: Wyłącz parowanie urządzeń Control UI (lan_https) + description: "Gdy WŁĄCZONE (zalecane), ustawia gateway.controlUi.dangerouslyDisableDeviceAuth=true, pomija akceptację per-urządzenie i zapobiega błędowi 1008 w trybie LAN HTTPS. Zostaw WŁĄCZONE w domowej/zaufanej sieci. Wyłącz tylko jeśli chcesz ścisłe parowanie dla każdej nowej przeglądarki/urządzenia." + gateway_bind_mode: name: Tryb bindowania Gateway description: Tryb bindowania sieci - loopback (tylko 127.0.0.1, najbezpieczniejszy), lan (wszystkie interfejsy) lub tailnet (tylko interfejs Tailscale). Nadpisywane przez ustawienia trybu dostępu. diff --git a/openclaw_assistant/translations/pt-BR.yaml b/openclaw_assistant/translations/pt-BR.yaml index 65b1603..8dce12e 100644 --- a/openclaw_assistant/translations/pt-BR.yaml +++ b/openclaw_assistant/translations/pt-BR.yaml @@ -58,6 +58,10 @@ configuration: name: Origens permitidas adicionais description: Origens extras da Control UI separadas por vírgula, mescladas em gateway.controlUi.allowedOrigins no modo lan_https (exemplo - https://ha.example.com:8443,capacitor://localhost) + controlui_disable_device_auth: + name: Desativar pareamento por dispositivo no Control UI (lan_https) + description: "Quando LIGADO (recomendado), define gateway.controlUi.dangerouslyDisableDeviceAuth=true para pular aprovação por dispositivo e evitar erro 1008 no modo LAN HTTPS. Mantenha LIGADO em rede doméstica/confiável. Desligue apenas se quiser pareamento estrito para cada novo navegador/dispositivo." + gateway_bind_mode: name: Modo de Vinculação do Gateway description: Modo de vinculação de rede - loopback (somente 127.0.0.1, mais seguro), lan (todas as interfaces) ou tailnet (somente interface Tailscale). Substituído pelas predefinições do modo de acesso.