ClawBox has one human password and several machine tokens. Understanding which is which resolves most “can’t log in” confusion.

The one password

The browser/desktop login and SSH use the same Linux system password (account clawbox). 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 chpasswd step.
  • sudo passwd clawbox (SSH) — takes effect for the browser immediately.
  • Factory reset — resets it to clawbox.

Browser login flow

Requirements for this to work (the checklist behind “SSH accepts it, browser doesn’t”):
  1. The web app must resolve the right username — CLAWBOX_USER env → SUDO_USER → USER → OS user, default clawbox.
  2. /usr/sbin/unix_chkpwd must be setgid shadow (-rwxr-sr-x root shadow) — it’s the PAM helper that reads /etc/shadow on 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.
  3. The running build must be current — a stale build from a half-finished update checks with old logic.
  4. The password bytes the browser sends must match — non-ASCII passwords can be encoded differently by the browser vs the terminal that set them.
The full diagnostic ladder for login failures is in Troubleshooting.

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 at openclaw.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-config and injected HTML) — users never type it.
  • The gateway service is started without --token so the config value is the single source of truth. A stale service file that still passes --token causes the classic unauthorized: gateway token mismatch error — fix with sudo 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.
  • A default-deny inbound firewall (ufw) ships on the device: only SSH (22), the web OS (80, and 443 when certs are installed at data/certs/), the gateway (18789) and the Hermes dashboard proxy (8090) are reachable. On IPv4 that is further scoped to private LAN/Tailscale source ranges; IPv6 is not source-scoped — there is no RFC1918 equivalent and a normal dual-stack LAN hands the box a global address, which is exactly what avahi publishes for clawbox.local; on v6 the site router is the boundary. mDNS, plus DHCP and captive-portal DNS on the hotspot interface, stay open so discovery and the AP keep working. Everything else that happens to bind 0.0.0.0 (CUPS on 631, rpcbind on 111, the terminal PTY on 3006, Syncthing on 8384) is closed to the LAN.
  • 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.
  • On the Hermes edition the agent scans every shell command with tirith before running it. The scanner is not shipped — the agent downloads it the first time the box is online — and upstream’s default is fail-open, so a box that has never had internet runs commands unscanned. Settings → System reports that state instead of leaving it silent, and security.tirith_fail_open: false in ~/.hermes/config.yaml switches the agent to refusing commands it cannot scan.
  • Factory reset wipes credentials, SSH keys, histories, and browser profiles — see Recovery.
  • Vulnerability reports: see SECURITY.md.