From 97248a2885da7760db9149f3584da59bfd80b34c Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 26 Jan 2026 19:58:54 +0000 Subject: [PATCH] feat: surface security audit + docs --- docs/channels/discord.md | 9 +++++---- docs/start/getting-started.md | 5 +++++ docs/start/setup.md | 12 ++++++++++++ docs/tools/skills.md | 8 ++++++++ docs/web/dashboard.md | 4 ++++ ui/src/ui/views/debug.ts | 22 ++++++++++++++++++++++ 6 files changed, 56 insertions(+), 4 deletions(-) diff --git a/docs/channels/discord.md b/docs/channels/discord.md index 12dd28084..395f13c6a 100644 --- a/docs/channels/discord.md +++ b/docs/channels/discord.md @@ -10,13 +10,14 @@ Status: ready for DM and guild text channels via the official Discord bot gatewa ## Quick setup (beginner) 1) Create a Discord bot and copy the bot token. -2) Set the token for Clawdbot: +2) In the Discord app settings, enable **Message Content Intent** (and **Server Members Intent** if you plan to use allowlists or name lookups). +3) Set the token for Clawdbot: - Env: `DISCORD_BOT_TOKEN=...` - Or config: `channels.discord.token: "..."`. - If both are set, config takes precedence (env fallback is default-account only). -3) Invite the bot to your server with message permissions. -4) Start the gateway. -5) DM access is pairing by default; approve the pairing code on first contact. +4) Invite the bot to your server with message permissions (create a private server if you just want DMs). +5) Start the gateway. +6) DM access is pairing by default; approve the pairing code on first contact. Minimal config: ```json5 diff --git a/docs/start/getting-started.md b/docs/start/getting-started.md index dd68b8f55..00bc00efb 100644 --- a/docs/start/getting-started.md +++ b/docs/start/getting-started.md @@ -9,6 +9,10 @@ read_when: Goal: go from **zero** → **first working chat** (with sane defaults) as quickly as possible. +Fastest chat: open the Control UI (no channel setup needed). Run `clawdbot dashboard` +and chat in the browser, or open `http://127.0.0.1:18789/` on the gateway host. +Docs: [Dashboard](/web/dashboard) and [Control UI](/web/control-ui). + Recommended path: use the **CLI onboarding wizard** (`clawdbot onboard`). It sets up: - model/auth (OAuth recommended) - gateway settings @@ -121,6 +125,7 @@ channels. If you use WhatsApp or Telegram, run the Gateway with **Node**. ```bash clawdbot status clawdbot health +clawdbot security audit --deep ``` ## 4) Pair + connect your first chat surface diff --git a/docs/start/setup.md b/docs/start/setup.md index 587b7fd6b..f4024a50d 100644 --- a/docs/start/setup.md +++ b/docs/start/setup.md @@ -104,6 +104,18 @@ clawdbot health - Sessions: `~/.clawdbot/agents//sessions/` - Logs: `/tmp/clawdbot/` +## Credential storage map + +Use this when debugging auth or deciding what to back up: + +- **WhatsApp**: `~/.clawdbot/credentials/whatsapp//creds.json` +- **Telegram bot token**: config/env or `channels.telegram.tokenFile` +- **Discord bot token**: config/env (token file not yet supported) +- **Slack tokens**: config/env (`channels.slack.*`) +- **Pairing allowlists**: `~/.clawdbot/credentials/-allowFrom.json` +- **Model auth profiles**: `~/.clawdbot/agents//agent/auth-profiles.json` +- **Legacy OAuth import**: `~/.clawdbot/credentials/oauth.json` + ## Updating (without wrecking your setup) - Keep `~/clawd` and `~/.clawdbot/` as “your stuff”; don’t put personal prompts/config into the `clawdbot` repo. diff --git a/docs/tools/skills.md b/docs/tools/skills.md index 289118bae..d9c840d73 100644 --- a/docs/tools/skills.md +++ b/docs/tools/skills.md @@ -64,6 +64,14 @@ By default, `clawdhub` installs into `./skills` under your current working directory (or falls back to the configured Clawdbot workspace). Clawdbot picks that up as `/skills` on the next session. +## Security notes + +- Treat third-party skills as **trusted code**. Read them before enabling. +- Prefer sandboxed runs for untrusted inputs and risky tools. See [Sandboxing](/gateway/sandboxing). +- `skills.entries.*.env` and `skills.entries.*.apiKey` inject secrets into the **host** process + for that agent turn (not the sandbox). Keep secrets out of prompts and logs. +- For a broader threat model and checklists, see [Security](/gateway/security). + ## Format (AgentSkills + Pi-compatible) `SKILL.md` must include at least: diff --git a/docs/web/dashboard.md b/docs/web/dashboard.md index 81d0aacc4..fdbf209be 100644 --- a/docs/web/dashboard.md +++ b/docs/web/dashboard.md @@ -19,6 +19,10 @@ Key references: Authentication is enforced at the WebSocket handshake via `connect.params.auth` (token or password). See `gateway.auth` in [Gateway configuration](/gateway/configuration). +Security note: the Control UI is an **admin surface** (chat, config, exec approvals). +Do not expose it publicly. The UI stores the token in `localStorage` after first load. +Prefer localhost, Tailscale Serve, or an SSH tunnel. + ## Fast path (recommended) - After onboarding, the CLI now auto-opens the dashboard with your token and prints the same tokenized link. diff --git a/ui/src/ui/views/debug.ts b/ui/src/ui/views/debug.ts index 35e2e1af2..d33eaffc7 100644 --- a/ui/src/ui/views/debug.ts +++ b/ui/src/ui/views/debug.ts @@ -21,6 +21,22 @@ export type DebugProps = { }; export function renderDebug(props: DebugProps) { + const securityAudit = + props.status && typeof props.status === "object" + ? (props.status as { securityAudit?: { summary?: Record } }).securityAudit + : null; + const securitySummary = securityAudit?.summary ?? null; + const critical = securitySummary?.critical ?? 0; + const warn = securitySummary?.warn ?? 0; + const info = securitySummary?.info ?? 0; + const securityTone = critical > 0 ? "danger" : warn > 0 ? "warn" : "success"; + const securityLabel = + critical > 0 + ? `${critical} critical` + : warn > 0 + ? `${warn} warnings` + : "No critical issues"; + return html`
@@ -36,6 +52,12 @@ export function renderDebug(props: DebugProps) {
Status
+ ${securitySummary + ? html`
+ Security audit: ${securityLabel}${info > 0 ? ` · ${info} info` : ""}. Run + clawdbot security audit --deep for details. +
` + : nothing}
${JSON.stringify(props.status ?? {}, null, 2)}