mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-18 09:07:26 +00:00
fix(security): lock down inbound DMs by default
This commit is contained in:
@@ -184,15 +184,28 @@ Metadata written by CLI wizards (`onboard`, `configure`, `doctor`, `update`).
|
||||
}
|
||||
```
|
||||
|
||||
### `whatsapp.dmPolicy`
|
||||
|
||||
Controls how WhatsApp direct chats (DMs) are handled:
|
||||
- `"pairing"` (default): unknown senders get a pairing code; owner must approve
|
||||
- `"allowlist"`: only allow senders in `whatsapp.allowFrom` (or paired allow store)
|
||||
- `"open"`: allow all inbound DMs (**requires** `whatsapp.allowFrom` to include `"*"`)
|
||||
- `"disabled"`: ignore all inbound DMs
|
||||
|
||||
Pairing approvals:
|
||||
- `clawdbot pairing list --provider whatsapp`
|
||||
- `clawdbot pairing approve --provider whatsapp <code>`
|
||||
|
||||
### `whatsapp.allowFrom`
|
||||
|
||||
Allowlist of E.164 phone numbers that may trigger WhatsApp auto-replies (**DMs only**).
|
||||
If empty, the default allowlist is your own WhatsApp number (self-chat mode).
|
||||
If empty and `whatsapp.dmPolicy="pairing"`, unknown senders will receive a pairing code.
|
||||
For groups, use `whatsapp.groupPolicy` + `whatsapp.groupAllowFrom`.
|
||||
|
||||
```json5
|
||||
{
|
||||
whatsapp: {
|
||||
dmPolicy: "pairing", // pairing | allowlist | open | disabled
|
||||
allowFrom: ["+15555550123", "+447700900123"],
|
||||
textChunkLimit: 4000 // optional outbound chunk size (chars)
|
||||
}
|
||||
@@ -338,8 +351,9 @@ Set `telegram.enabled: false` to disable automatic startup.
|
||||
telegram: {
|
||||
enabled: true,
|
||||
botToken: "your-bot-token",
|
||||
requireMention: true,
|
||||
allowFrom: ["123456789"],
|
||||
dmPolicy: "pairing", // pairing | allowlist | open | disabled
|
||||
allowFrom: ["tg:123456789"], // optional; "open" requires ["*"]
|
||||
groups: { "*": { requireMention: true } },
|
||||
mediaMaxMb: 5,
|
||||
proxy: "socks5://localhost:9050",
|
||||
webhookUrl: "https://example.com/telegram-webhook",
|
||||
@@ -385,7 +399,8 @@ Configure the Discord bot by setting the bot token and optional gating:
|
||||
},
|
||||
dm: {
|
||||
enabled: true, // disable all DMs when false
|
||||
allowFrom: ["1234567890", "steipete"], // optional DM allowlist (ids or names)
|
||||
policy: "pairing", // pairing | allowlist | open | disabled
|
||||
allowFrom: ["1234567890", "steipete"], // optional DM allowlist ("open" requires ["*"])
|
||||
groupEnabled: false, // enable group DMs
|
||||
groupChannels: ["clawd-dm"] // optional group DM allowlist
|
||||
},
|
||||
@@ -426,7 +441,8 @@ Slack runs in Socket Mode and requires both a bot token and app token:
|
||||
appToken: "xapp-...",
|
||||
dm: {
|
||||
enabled: true,
|
||||
allowFrom: ["U123", "U456", "*"],
|
||||
policy: "pairing", // pairing | allowlist | open | disabled
|
||||
allowFrom: ["U123", "U456", "*"], // optional; "open" requires ["*"]
|
||||
groupEnabled: false,
|
||||
groupChannels: ["G123"]
|
||||
},
|
||||
@@ -481,6 +497,7 @@ Clawdbot spawns `imsg rpc` (JSON-RPC over stdio). No daemon or port required.
|
||||
enabled: true,
|
||||
cliPath: "imsg",
|
||||
dbPath: "~/Library/Messages/chat.db",
|
||||
dmPolicy: "pairing", // pairing | allowlist | open | disabled
|
||||
allowFrom: ["+15555550123", "user@example.com", "chat_id:123"],
|
||||
includeAttachments: false,
|
||||
mediaMaxMb: 16,
|
||||
|
||||
@@ -23,11 +23,15 @@ Status: ready for DM and guild text channels via the official Discord bot gatewa
|
||||
- If you prefer env vars, still add `discord: { enabled: true }` to `~/.clawdbot/clawdbot.json` and set `DISCORD_BOT_TOKEN`.
|
||||
5. Direct chats: use `user:<id>` (or a `<@id>` mention) when delivering; all turns land in the shared `main` session.
|
||||
6. Guild channels: use `channel:<channelId>` for delivery. Mentions are required by default and can be set per guild or per channel.
|
||||
7. Optional DM control: set `discord.dm.enabled = false` to ignore all DMs, or `discord.dm.allowFrom` to allow specific users (ids or names). Use `discord.dm.groupEnabled` + `discord.dm.groupChannels` to allow group DMs.
|
||||
8. Optional guild rules: set `discord.guilds` keyed by guild id (preferred) or slug, with per-channel rules.
|
||||
9. Optional slash commands: enable `discord.slashCommand` to accept user-installed app commands (ephemeral replies). Slash invocations respect the same DM/guild allowlists.
|
||||
10. Optional guild context history: set `discord.historyLimit` (default 20) to include the last N guild messages as context when replying to a mention. Set `0` to disable.
|
||||
11. Reactions: the agent can trigger reactions via the `discord` tool (gated by `discord.actions.*`).
|
||||
7. Direct chats: secure by default via `discord.dm.policy` (default: `"pairing"`). Unknown senders get a pairing code; approve via `clawdbot pairing approve --provider discord <code>`.
|
||||
- To keep old “open to anyone” behavior: set `discord.dm.policy="open"` and `discord.dm.allowFrom=["*"]`.
|
||||
- To hard-allowlist: set `discord.dm.policy="allowlist"` and list senders in `discord.dm.allowFrom`.
|
||||
- To ignore all DMs: set `discord.dm.enabled=false` or `discord.dm.policy="disabled"`.
|
||||
8. Group DMs are ignored by default; enable via `discord.dm.groupEnabled` and optionally restrict by `discord.dm.groupChannels`.
|
||||
9. Optional guild rules: set `discord.guilds` keyed by guild id (preferred) or slug, with per-channel rules.
|
||||
10. Optional slash commands: enable `discord.slashCommand` to accept user-installed app commands (ephemeral replies). Slash invocations respect the same DM/guild allowlists.
|
||||
11. Optional guild context history: set `discord.historyLimit` (default 20) to include the last N guild messages as context when replying to a mention. Set `0` to disable.
|
||||
12. Reactions: the agent can trigger reactions via the `discord` tool (gated by `discord.actions.*`).
|
||||
- The `discord` tool is only exposed when the current surface is Discord.
|
||||
12. Slash commands use isolated session keys (`${sessionPrefix}:${userId}`) rather than the shared `main` session.
|
||||
|
||||
@@ -138,7 +142,7 @@ Notes:
|
||||
- The bot lacks channel permissions (View/Send/Read History), or
|
||||
- Your config requires mentions and you didn’t mention it, or
|
||||
- Your guild/channel allowlist denies the channel/user.
|
||||
- **DMs don’t work**: `discord.dm.enabled` may be `false` or `discord.dm.allowFrom` doesn’t include you.
|
||||
- **DMs don’t work**: `discord.dm.enabled=false`, `discord.dm.policy="disabled"`, or you haven’t been approved yet (`discord.dm.policy="pairing"`).
|
||||
|
||||
## Capabilities & limits
|
||||
- DMs and guild text channels (threads are treated as separate channels; voice not supported).
|
||||
@@ -183,6 +187,7 @@ Notes:
|
||||
},
|
||||
dm: {
|
||||
enabled: true,
|
||||
policy: "pairing", // pairing | allowlist | open | disabled
|
||||
allowFrom: ["123456789012345678", "steipete"],
|
||||
groupEnabled: false,
|
||||
groupChannels: ["clawd-dm"]
|
||||
@@ -208,7 +213,8 @@ Ack reactions are controlled globally via `messages.ackReaction` +
|
||||
`messages.ackReactionScope`.
|
||||
|
||||
- `dm.enabled`: set `false` to ignore all DMs (default `true`).
|
||||
- `dm.allowFrom`: DM allowlist (user ids or names). Omit or set to `["*"]` to allow any DM sender.
|
||||
- `dm.policy`: DM access control (`pairing` recommended). `"open"` requires `dm.allowFrom=["*"]`.
|
||||
- `dm.allowFrom`: DM allowlist (user ids or names). Used by `dm.policy="allowlist"` and for `dm.policy="open"` validation.
|
||||
- `dm.groupEnabled`: enable group DMs (default `false`).
|
||||
- `dm.groupChannels`: optional allowlist for group DM channel ids or slugs.
|
||||
- `groupPolicy`: controls guild channel handling (`open|disabled|allowlist`); `allowlist` requires channel allowlists.
|
||||
|
||||
@@ -18,7 +18,7 @@ Updated: 2025-12-07
|
||||
- **Proxy:** optional `telegram.proxy` uses `undici.ProxyAgent` through grammY’s `client.baseFetch`.
|
||||
- **Webhook support:** `webhook-set.ts` wraps `setWebhook/deleteWebhook`; `webhook.ts` hosts the callback with health + graceful shutdown. Gateway enables webhook mode when `telegram.webhookUrl` is set (otherwise it long-polls).
|
||||
- **Sessions:** direct chats map to `main`; groups map to `telegram:group:<chatId>`; replies route back to the same surface.
|
||||
- **Config knobs:** `telegram.botToken`, `telegram.groups` (allowlist + mention defaults), `telegram.allowFrom`, `telegram.mediaMaxMb`, `telegram.proxy`, `telegram.webhookSecret`, `telegram.webhookUrl`.
|
||||
- **Config knobs:** `telegram.botToken`, `telegram.dmPolicy`, `telegram.groups` (allowlist + mention defaults), `telegram.allowFrom`, `telegram.groupAllowFrom`, `telegram.groupPolicy`, `telegram.mediaMaxMb`, `telegram.proxy`, `telegram.webhookSecret`, `telegram.webhookUrl`.
|
||||
- **Tests:** grammy mocks cover DM + group mention gating and outbound send; more media/webhook fixtures still welcome.
|
||||
|
||||
Open questions
|
||||
|
||||
@@ -26,6 +26,7 @@ Status: external CLI integration. No daemon.
|
||||
enabled: true,
|
||||
cliPath: "imsg",
|
||||
dbPath: "~/Library/Messages/chat.db",
|
||||
dmPolicy: "pairing", // pairing | allowlist | open | disabled
|
||||
allowFrom: ["+15555550123", "user@example.com", "chat_id:123"],
|
||||
groupPolicy: "open",
|
||||
groupAllowFrom: ["chat_id:123"],
|
||||
@@ -39,6 +40,7 @@ Status: external CLI integration. No daemon.
|
||||
|
||||
Notes:
|
||||
- `allowFrom` accepts handles (phone/email) or `chat_id:<id>` entries.
|
||||
- Default: `imessage.dmPolicy="pairing"` — unknown DM senders get a pairing code (approve via `clawdbot pairing approve --provider imessage <code>`). `"open"` requires `allowFrom=["*"]`.
|
||||
- `groupPolicy` controls group handling (`open|disabled|allowlist`).
|
||||
- `groupAllowFrom` accepts the same entries as `allowFrom`.
|
||||
- `service` defaults to `auto` (use `imessage` or `sms` to pin).
|
||||
|
||||
@@ -49,6 +49,7 @@ This is social engineering 101. Create distrust, encourage snooping.
|
||||
```
|
||||
|
||||
Only allow specific phone numbers to trigger your AI. Never use `["*"]` in production.
|
||||
Newer versions default to **DM pairing** (`*.dmPolicy="pairing"`) on most providers; avoid `dmPolicy="open"` unless you explicitly want public inbound access.
|
||||
|
||||
### 2. Group Chat Mentions
|
||||
|
||||
|
||||
@@ -51,7 +51,8 @@ You can still run Clawdbot on your own Signal account if your goal is “respond
|
||||
httpPort: 8080,
|
||||
|
||||
// Who is allowed to talk to the bot (DMs)
|
||||
allowFrom: ["+15557654321"], // your personal number (or "*")
|
||||
dmPolicy: "pairing", // pairing | allowlist | open | disabled
|
||||
allowFrom: ["+15557654321"], // your personal number ("open" requires ["*"])
|
||||
|
||||
// Group policy + allowlist
|
||||
groupPolicy: "open",
|
||||
@@ -64,6 +65,10 @@ You can still run Clawdbot on your own Signal account if your goal is “respond
|
||||
- Expect `signal.probe.ok=true` and `signal.probe.version`.
|
||||
5) DM the bot number from your phone; Clawdbot replies.
|
||||
|
||||
## DM pairing
|
||||
- Default: `signal.dmPolicy="pairing"` — unknown DM senders get a pairing code.
|
||||
- Approve via: `clawdbot pairing approve --provider signal <code>`.
|
||||
|
||||
## “Do I need a separate number?”
|
||||
- If you want “I text her and she texts me back”, yes: **use a separate Signal account/number for the bot**.
|
||||
- Your personal account can run `signal-cli`, but you can’t self-chat (Signal loop protection; Clawdbot ignores sender==account).
|
||||
|
||||
@@ -148,6 +148,7 @@ Slack uses Socket Mode only (no HTTP webhook server). Provide both tokens:
|
||||
"groupPolicy": "open",
|
||||
"dm": {
|
||||
"enabled": true,
|
||||
"policy": "pairing",
|
||||
"allowFrom": ["U123", "U456", "*"],
|
||||
"groupEnabled": false,
|
||||
"groupChannels": ["G123"]
|
||||
@@ -189,6 +190,11 @@ Ack reactions are controlled globally via `messages.ackReaction` +
|
||||
- Channels map to `slack:channel:<channelId>` sessions.
|
||||
- Slash commands use `slack:slash:<userId>` sessions.
|
||||
|
||||
## DM security (pairing)
|
||||
- Default: `slack.dm.policy="pairing"` — unknown DM senders get a pairing code.
|
||||
- Approve via: `clawdbot pairing approve --provider slack <code>`.
|
||||
- To allow anyone: set `slack.dm.policy="open"` and `slack.dm.allowFrom=["*"]`.
|
||||
|
||||
## Group policy
|
||||
- `slack.groupPolicy` controls channel handling (`open|disabled|allowlist`).
|
||||
- `allowlist` requires channels to be listed in `slack.channels`.
|
||||
|
||||
@@ -23,10 +23,10 @@ Status: ready for bot-mode use with grammY (long-polling by default; webhook sup
|
||||
- **Webhook mode** is enabled by setting `telegram.webhookUrl` (optionally `telegram.webhookSecret` / `telegram.webhookPath`).
|
||||
- The webhook listener currently binds to `0.0.0.0:8787` and serves `POST /telegram-webhook` by default.
|
||||
- If you need a different public port/host, set `telegram.webhookUrl` to the externally reachable URL and use a reverse proxy to forward to `:8787`.
|
||||
4) Direct chats: user sends the first message; all subsequent turns land in the shared `main` session (default, no extra config).
|
||||
4) Direct chats: secure by default — unknown senders are gated by `telegram.dmPolicy` (default: `"pairing"`). The bot responds with a pairing code that the owner must approve before messages are processed. If you really want public inbound DMs: set `telegram.dmPolicy="open"` and `telegram.allowFrom=["*"]`.
|
||||
5) Groups: add the bot, disable privacy mode (or make it admin) so it can read messages; group threads stay on `telegram:group:<chatId>`. When `telegram.groups` is set, it becomes a group allowlist (use `"*"` to allow all). Mention/command gating defaults come from `telegram.groups`.
|
||||
6) Optional allowlist:
|
||||
- Direct chats: `telegram.allowFrom` by chat id (`123456789`, `telegram:123456789`, or `tg:123456789`; prefixes are case-insensitive).
|
||||
6) Allowlist + pairing:
|
||||
- Direct chats: `telegram.allowFrom` (chat ids) or pairing approvals via `clawdbot pairing approve --provider telegram <code>` (alias: `clawdbot telegram pairing approve <code>`).
|
||||
- Groups: set `telegram.groupPolicy = "allowlist"` and list senders in `telegram.groupAllowFrom` (fallback: explicit `telegram.allowFrom`).
|
||||
|
||||
## Capabilities & limits (Bot API)
|
||||
@@ -39,7 +39,7 @@ Status: ready for bot-mode use with grammY (long-polling by default; webhook sup
|
||||
- Library: grammY is the only client for send + gateway (fetch fallback removed); grammY throttler is enabled by default to stay under Bot API limits.
|
||||
- Inbound normalization: maps Bot API updates to `MsgContext` with `Surface: "telegram"`, `ChatType: direct|group`, `SenderName`, `MediaPath`/`MediaType` when attachments arrive, `Timestamp`, and reply-to metadata (`ReplyToId`, `ReplyToBody`, `ReplyToSender`) when the user replies; reply context is appended to `Body` as a `[Replying to ...]` block (includes `id:` when available); groups require @bot mention or a `routing.groupChat.mentionPatterns` match by default (override per chat in config).
|
||||
- Outbound: text and media (photo/video/audio/document) with optional caption; chunked to limits. Typing cue sent best-effort.
|
||||
- Config: `TELEGRAM_BOT_TOKEN` env or `telegram.botToken` required; `telegram.groups` (group allowlist + mention defaults), `telegram.allowFrom`, `telegram.groupAllowFrom`, `telegram.groupPolicy`, `telegram.mediaMaxMb`, `telegram.replyToMode`, `telegram.proxy`, `telegram.webhookSecret`, `telegram.webhookUrl`, `telegram.webhookPath` supported.
|
||||
- Config: `TELEGRAM_BOT_TOKEN` env or `telegram.botToken` required; `telegram.dmPolicy`, `telegram.groups` (group allowlist + mention defaults), `telegram.allowFrom`, `telegram.groupAllowFrom`, `telegram.groupPolicy`, `telegram.mediaMaxMb`, `telegram.replyToMode`, `telegram.proxy`, `telegram.webhookSecret`, `telegram.webhookUrl`, `telegram.webhookPath` supported.
|
||||
- Ack reactions are controlled globally via `messages.ackReaction` + `messages.ackReactionScope`.
|
||||
- Mention gating precedence (most specific wins): `telegram.groups.<chatId>.requireMention` → `telegram.groups."*".requireMention` → default `true`.
|
||||
|
||||
@@ -49,12 +49,13 @@ Example config:
|
||||
telegram: {
|
||||
enabled: true,
|
||||
botToken: "123:abc",
|
||||
dmPolicy: "pairing", // pairing | allowlist | open | disabled
|
||||
replyToMode: "off",
|
||||
groups: {
|
||||
"*": { requireMention: true }, // allow all groups
|
||||
"123456789": { requireMention: false } // group chat id
|
||||
},
|
||||
allowFrom: ["123456789"], // direct chat ids allowed (or "*")
|
||||
allowFrom: ["123456789"], // direct chat ids allowed ("open" requires ["*"])
|
||||
groupPolicy: "allowlist",
|
||||
groupAllowFrom: ["tg:123456789", "@alice"],
|
||||
mediaMaxMb: 5,
|
||||
|
||||
@@ -47,8 +47,10 @@ WhatsApp requires a real mobile number for verification. VoIP and virtual number
|
||||
- Inbox listeners are detached on shutdown to avoid accumulating event handlers in tests/restarts.
|
||||
- Status/broadcast chats are ignored.
|
||||
- Direct chats use E.164; groups use group JID.
|
||||
- **Allowlist**: `whatsapp.allowFrom` enforced for direct chats only.
|
||||
- If `whatsapp.allowFrom` is empty, default allowlist = self number (self-chat mode).
|
||||
- **DM policy**: `whatsapp.dmPolicy` controls direct chat access (default: `pairing`).
|
||||
- Pairing: unknown senders get a pairing code (approve via `clawdbot pairing approve --provider whatsapp <code>`).
|
||||
- Open: requires `whatsapp.allowFrom` to include `"*"`.
|
||||
- Self messages are always allowed; “self-chat mode” still requires `whatsapp.allowFrom` to include your own number.
|
||||
- **Group policy**: `whatsapp.groupPolicy` controls group handling (`open|disabled|allowlist`).
|
||||
- `allowlist` uses `whatsapp.groupAllowFrom` (fallback: explicit `whatsapp.allowFrom`).
|
||||
- **Self-chat mode**: avoids auto read receipts and ignores mention JIDs.
|
||||
@@ -120,6 +122,7 @@ WhatsApp requires a real mobile number for verification. VoIP and virtual number
|
||||
- Logged-out => stop and require re-link.
|
||||
|
||||
## Config quick map
|
||||
- `whatsapp.dmPolicy` (DM policy: pairing/allowlist/open/disabled).
|
||||
- `whatsapp.allowFrom` (DM allowlist).
|
||||
- `whatsapp.groupAllowFrom` (group sender allowlist).
|
||||
- `whatsapp.groupPolicy` (group policy).
|
||||
|
||||
Reference in New Issue
Block a user