The one password
The browser/desktop login and SSH use the same Linux system password (accountclawbox). There is no separate admin or web password. Changing it anywhere changes it everywhere:
- Settings → System → Change password (web) — validated, rate-limited, applied via a privileged
chpasswdstep. sudo passwd clawbox(SSH) — takes effect for the browser immediately.- Factory reset — resets it to
clawbox.
Browser login flow
- The web app must resolve the right username —
CLAWBOX_USERenv →SUDO_USER→USER→ OS user, defaultclawbox. /usr/sbin/unix_chkpwdmust be setgidshadow(-rwxr-sr-x root shadow) — it’s the PAM helper that reads/etc/shadowon behalf of the non-root web app. SSH doesn’t need this (sshd is root), which is why SSH can work while the browser fails.- The running build must be current — a stale build from a half-finished update checks with old logic.
- The password bytes the browser sends must match — non-ASCII passwords can be encoded differently by the browser vs the terminal that set them.
Session cookies
clawbox_session is an HMAC-SHA256-signed expiry token (no server-side session store): base64url({exp}) + "." + HMAC(payload, secret). Durations: 20 min, 6 h, 12 h, or 24 h. The signing secret persists in data/.session-secret. Cookies are httpOnly, SameSite=Lax, and non-Secure (the LAN UI is plain HTTP).
Middleware enforces the cookie on every route except the public set (/login, /setup, static assets, captive-portal probes) — and skips enforcement entirely until first-boot setup completes.
Gateway token (machine, not human)
The OpenClaw gateway (port 18789) authenticates its WebSocket clients with a token stored atopenclaw.json → gateway.auth.token:
- Per-device random 32-byte hex — generated on first boot/reset and preserved thereafter. (Early builds shipped a public literal
"clawbox"; any such weak token is automatically rotated to a strong one on gateway start.) - The ClawBox UI injects this token into the OpenClaw Control UI automatically (via
/setup-api/gateway/ws-configand injected HTML) — users never type it. - The gateway service is started without
--tokenso the config value is the single source of truth. A stale service file that still passes--tokencauses the classicunauthorized: gateway token mismatcherror — fix withsudo bash install.sh --step gateway_setup.
Service-to-service tokens
All are per-install random values with
0600 permissions, seeded/re-hardened automatically at boot.
Provider credentials
AI provider keys and OAuth sessions are separate from all of the above — see AI Providers → Where credentials actually go for the full map.Security posture summary
- The gateway listens on the LAN but is token-gated (per-device random token); users go through the authenticated web app on port 80, which injects the token for them.
- Web login is rate-limited with lockout; passwords are never logged; control characters are rejected.
- Privileged operations run through an allowlisted systemd template (polkit + narrow sudoers), never arbitrary root exec from the web process.
- Telegram DMs default to pairing mode — unknown senders are inert until the owner approves their 8-character code. Config that would open DMs to everyone (
dmPolicy:"open"+allowFrom:["*"]) is actively stripped on boot. - Factory reset wipes credentials, SSH keys, histories, and browser profiles — see Recovery.
- Vulnerability reports: see SECURITY.md.

