docs(security): clarify canvas host exposure and auth

This commit is contained in:
Peter Steinberger
2026-02-14 14:55:10 +01:00
parent 8025e7c6c2
commit 6a386a7886
13 changed files with 35 additions and 21 deletions

View File

@@ -60,6 +60,7 @@ OpenClaw's web interface (Gateway Control UI + HTTP endpoints) is intended for *
- CLI: `openclaw gateway run --bind loopback`.
- Do **not** expose it to the public internet (no direct bind to `0.0.0.0`, no public reverse proxy). It is not hardened for public exposure.
- If you need remote access, prefer an SSH tunnel or Tailscale serve/funnel (so the Gateway still binds to loopback), plus strong Gateway auth.
- The Gateway HTTP surface includes the canvas host (`/__openclaw__/canvas/`, `/__openclaw__/a2ui/`). Treat canvas content as sensitive/untrusted and avoid exposing it beyond loopback unless you understand the risk.
## Runtime Requirements

View File

@@ -19,7 +19,10 @@ Last updated: 2026-01-22
- **Nodes** (macOS/iOS/Android/headless) also connect over **WebSocket**, but
declare `role: node` with explicit caps/commands.
- One Gateway per host; it is the only place that opens a WhatsApp session.
- A **canvas host** (default `18793`) serves agenteditable HTML and A2UI.
- The **canvas host** is served by the Gateway HTTP server under:
- `/__openclaw__/canvas/` (agent-editable HTML/CSS/JS)
- `/__openclaw__/a2ui/` (A2UI host)
It uses the same port as the Gateway (default `18789`).
## Components and flows

View File

@@ -94,7 +94,7 @@ The Gateway advertises small nonsecret hints to make UI flows convenient:
- `gatewayPort=<port>` (Gateway WS + HTTP)
- `gatewayTls=1` (only when TLS is enabled)
- `gatewayTlsSha256=<sha256>` (only when TLS is enabled and fingerprint is available)
- `canvasPort=<port>` (only when the canvas host is enabled; default `18793`)
- `canvasPort=<port>` (only when the canvas host is enabled; currently the same as `gatewayPort`)
- `sshPort=<port>` (defaults to 22 when not overridden)
- `transport=gateway`
- `cliPath=<path>` (optional; absolute path to a runnable `openclaw` entrypoint)

View File

@@ -2065,14 +2065,18 @@ Auth: `Authorization: Bearer <token>` or `x-openclaw-token: <token>`.
{
canvasHost: {
root: "~/.openclaw/workspace/canvas",
port: 18793,
liveReload: true,
// enabled: false, // or OPENCLAW_SKIP_CANVAS_HOST=1
},
}
```
- Serves HTML/CSS/JS over HTTP for iOS/Android nodes.
- Serves agent-editable HTML/CSS/JS and A2UI over HTTP under the Gateway port:
- `http://<gateway-host>:<gateway.port>/__openclaw__/canvas/`
- `http://<gateway-host>:<gateway.port>/__openclaw__/a2ui/`
- Local-only: keep `gateway.bind: "loopback"` (default).
- Non-loopback binds: canvas routes require Gateway auth (token/password/trusted-proxy), same as other Gateway HTTP surfaces.
- Node WebViews typically don't send auth headers; after a node is paired and connected, the Gateway allows a private-IP fallback so the node can load canvas/A2UI without leaking secrets into URLs.
- Injects live-reload client into served HTML.
- Auto-creates starter `index.html` when empty.
- Also serves A2UI at `/__openclaw__/a2ui/`.

View File

@@ -64,7 +64,7 @@ Troubleshooting and beacon details: [Bonjour](/gateway/bonjour).
- `gatewayPort=18789` (Gateway WS + HTTP)
- `gatewayTls=1` (only when TLS is enabled)
- `gatewayTlsSha256=<sha256>` (only when TLS is enabled and fingerprint is available)
- `canvasPort=18793` (default canvas host port; serves `/__openclaw__/canvas/`)
- `canvasPort=<port>` (canvas host port; currently the same as `gatewayPort` when the canvas host is enabled)
- `cliPath=<path>` (optional; absolute path to a runnable `openclaw` entrypoint or binary)
- `tailnetDns=<magicdns>` (optional hint; auto-detected when Tailscale is available)

View File

@@ -79,7 +79,7 @@ openclaw --profile rescue gateway install
Base port = `gateway.port` (or `OPENCLAW_GATEWAY_PORT` / `--port`).
- browser control service port = base + 2 (loopback only)
- `canvasHost.port = base + 4`
- canvas host is served on the Gateway HTTP server (same port as `gateway.port`)
- Browser profile CDP ports auto-allocate from `browser.controlPort + 9 .. + 108`
If you override any of these in config or env, you must keep them unique per instance.

View File

@@ -13,5 +13,8 @@ process that owns channel connections and the WebSocket control plane.
- One Gateway per host is recommended. It is the only process allowed to own the WhatsApp Web session. For rescue bots or strict isolation, run multiple gateways with isolated profiles and ports. See [Multiple gateways](/gateway/multiple-gateways).
- Loopback first: the Gateway WS defaults to `ws://127.0.0.1:18789`. The wizard generates a gateway token by default, even for loopback. For tailnet access, run `openclaw gateway --bind tailnet --token ...` because tokens are required for non-loopback binds.
- Nodes connect to the Gateway WS over LAN, tailnet, or SSH as needed. The legacy TCP bridge is deprecated.
- Canvas host is an HTTP file server on `canvasHost.port` (default `18793`) serving `/__openclaw__/canvas/` for node WebViews. See [Gateway configuration](/gateway/configuration) (`canvasHost`).
- Canvas host is served by the Gateway HTTP server on the **same port** as the Gateway (default `18789`):
- `/__openclaw__/canvas/`
- `/__openclaw__/a2ui/`
When `gateway.auth` is configured and the Gateway binds beyond loopback, these routes are protected by Gateway auth (loopback requests are exempt). See [Gateway configuration](/gateway/configuration) (`canvasHost`, `gateway`).
- Remote use is typically SSH tunnel or tailnet VPN. See [Remote access](/gateway/remote) and [Discovery](/gateway/discovery).

View File

@@ -347,6 +347,16 @@ The Gateway multiplexes **WebSocket + HTTP** on a single port:
- Default: `18789`
- Config/flags/env: `gateway.port`, `--port`, `OPENCLAW_GATEWAY_PORT`
This HTTP surface includes the Control UI and the canvas host:
- Control UI (SPA assets) (default base path `/`)
- Canvas host: `/__openclaw__/canvas/` and `/__openclaw__/a2ui/` (arbitrary HTML/JS; treat as untrusted content)
If you load canvas content in a normal browser, treat it like any other untrusted web page:
- Don't expose the canvas host to untrusted networks/users.
- Don't make canvas content share the same origin as privileged web surfaces unless you fully understand the implications.
Bind mode controls where the Gateway listens:
- `gateway.bind: "loopback"` (default): only local clients can connect.

View File

@@ -266,10 +266,6 @@ services:
# Recommended: keep the Gateway loopback-only on the VM; access via SSH tunnel.
# To expose it publicly, remove the `127.0.0.1:` prefix and firewall accordingly.
- "127.0.0.1:${OPENCLAW_GATEWAY_PORT}:18789"
# Optional: only if you run iOS/Android nodes against this VM and need Canvas host.
# If you expose this publicly, read /gateway/security and firewall accordingly.
# - "18793:18793"
command:
[
"node",

View File

@@ -177,10 +177,6 @@ services:
# Recommended: keep the Gateway loopback-only on the VPS; access via SSH tunnel.
# To expose it publicly, remove the `127.0.0.1:` prefix and firewall accordingly.
- "127.0.0.1:${OPENCLAW_GATEWAY_PORT}:18789"
# Optional: only if you run iOS/Android nodes against this VPS and need Canvas host.
# If you expose this publicly, read /gateway/security and firewall accordingly.
# - "18793:18793"
command:
[
"node",

View File

@@ -123,20 +123,20 @@ The Android nodes Chat sheet uses the gateways **primary session key** (`m
If you want the node to show real HTML/CSS/JS that the agent can edit on disk, point the node at the Gateway canvas host.
Note: nodes use the standalone canvas host on `canvasHost.port` (default `18793`).
Note: nodes load canvas from the Gateway HTTP server (same port as `gateway.port`, default `18789`).
1. Create `~/.openclaw/workspace/canvas/index.html` on the gateway host.
2. Navigate the node to it (LAN):
```bash
openclaw nodes invoke --node "<Android Node>" --command canvas.navigate --params '{"url":"http://<gateway-hostname>.local:18793/__openclaw__/canvas/"}'
openclaw nodes invoke --node "<Android Node>" --command canvas.navigate --params '{"url":"http://<gateway-hostname>.local:18789/__openclaw__/canvas/"}'
```
Tailnet (optional): if both devices are on Tailscale, use a MagicDNS name or tailnet IP instead of `.local`, e.g. `http://<gateway-magicdns>:18793/__openclaw__/canvas/`.
Tailnet (optional): if both devices are on Tailscale, use a MagicDNS name or tailnet IP instead of `.local`, e.g. `http://<gateway-magicdns>:18789/__openclaw__/canvas/`.
This server injects a live-reload client into HTML and reloads on file changes.
The A2UI host lives at `http://<gateway-host>:18793/__openclaw__/a2ui/`.
The A2UI host lives at `http://<gateway-host>:18789/__openclaw__/a2ui/`.
Canvas commands (foreground only):

View File

@@ -69,12 +69,13 @@ In Settings, enable **Manual Host** and enter the gateway host + port (default `
The iOS node renders a WKWebView canvas. Use `node.invoke` to drive it:
```bash
openclaw nodes invoke --node "iOS Node" --command canvas.navigate --params '{"url":"http://<gateway-host>:18793/__openclaw__/canvas/"}'
openclaw nodes invoke --node "iOS Node" --command canvas.navigate --params '{"url":"http://<gateway-host>:18789/__openclaw__/canvas/"}'
```
Notes:
- The Gateway canvas host serves `/__openclaw__/canvas/` and `/__openclaw__/a2ui/`.
- It is served from the Gateway HTTP server (same port as `gateway.port`, default `18789`).
- The iOS node auto-navigates to A2UI on connect when a canvas host URL is advertised.
- Return to the built-in scaffold with `canvas.navigate` and `{"url":""}`.

View File

@@ -73,7 +73,7 @@ A2UI host page on first open.
Default A2UI host URL:
```
http://<gateway-host>:18793/__openclaw__/a2ui/
http://<gateway-host>:18789/__openclaw__/a2ui/
```
### A2UI commands (v0.8)