- Heartbeat now requires explicit target by default (throws error) - Empty automation.recipients blocks all automation sends - Send logging shows correct resolution source (explicit/directory/fallback) - Delivery context has 24h TTL and clears on channel logout - Legacy WhatsApp adapter now has automation checks - Request logging for all send operations - First-time recipient warnings - Dry-run mode support (CLAWDBOT_DRY_RUN=true) - Security documentation added
8.7 KiB
| title | layout | nav_order | parent |
|---|---|---|---|
| Outbound Messaging Security Model | default | 1 | Security |
Outbound Messaging Security Model
This document explains Clawdbot's outbound messaging security model, including allowlist enforcement, target resolution, sub-agent messaging best practices, and automation recipient configuration.
Overview
Clawdbot implements multiple layers of security for outbound messaging to prevent unauthorized message sends:
- Allowlist Enforcement - Validates targets against configured allowlists
- Automation Recipients - Separate allowlist for automated/system sends
- Sub-Agent Restrictions - Blocks direct message sends from sub-agents
- Target Resolution - Controlled resolution of message targets
- Request Logging - Full audit trail of all send operations
- First-Time Recipient Warnings - Alerts for sends to new recipients
- Dry-Run Mode - Development/testing mode to prevent accidental sends
Allowlist Enforcement
Configuration
Allowlists are configured per channel. For WhatsApp:
{
"channels": {
"whatsapp": {
"allowFrom": ["+16505551234", "+16505555678"],
"accounts": {
"default": {
"allowFrom": ["+16505551234"]
}
}
}
}
}
Enforcement Rules
-
Explicit Mode Sends (CLI with
--target, direct API calls):- Target MUST be in allowlist OR use
--allow-unlistedflag - Groups are always allowed (no allowlist check)
- Empty allowlist = all targets allowed
- Target MUST be in allowlist OR use
-
Implicit Mode Sends (session-derived routing):
- If target not in allowlist, falls back to first allowlist entry
- Provides safe default behavior
-
Heartbeat/Automation Mode Sends:
- Validates against
automation.recipientsif configured - Falls back to general allowlist if automation.recipients is empty
- Validates against
Security Bypass
The --allow-unlisted CLI flag allows sending to targets not in the allowlist:
clawdbot message send --target +16505559999 --message "Hello" --allow-unlisted
This is logged and should only be used for emergencies.
Automation Recipients
Purpose
The automation.recipients list provides a stricter allowlist specifically for automated sends (heartbeats, cron jobs, system events, daemon notifications).
Configuration
{
"channels": {
"whatsapp": {
"automation": {
"recipients": ["+16505551234"]
},
"accounts": {
"default": {
"automation": {
"recipients": ["+16505551234"]
}
}
}
}
}
}
Behavior
- If
automation.recipientsis configured (non-empty), only those numbers can receive automated sends - If empty/not configured, falls back to general
allowFrombehavior - This separation prevents automation from accidentally messaging contacts that are allowed for interactive use but shouldn't receive automated notifications
Sub-Agent Messaging Restrictions
Default Behavior (FIX-1.5)
By default, sub-agents CANNOT directly call clawdbot message send or the message RPC API. This prevents:
- Prompt injection attacks causing sub-agents to spam messages
- Sub-agents bypassing session routing controls
- Accidental sends from poorly-written sub-agent prompts
Blocked Actions
send- Direct message sendspoll- Poll creationbroadcast- Broadcast sends
Allowed Actions
Sub-agents can still use:
sessions_sendtool - Routes through parent session context- Blessed callback mechanisms that go through proper routing
Security Logging
Blocked attempts are logged:
[security] Subagent agent:main:subagent:abc123 attempted direct message send - blocked
Override (Not Recommended)
To allow direct sends (use with caution):
{
"agents": {
"defaults": {
"subagents": {
"allowDirectMessageSend": true
}
}
}
}
Target Resolution Behavior
Resolution Modes
- Explicit - Target specified directly by user/caller
- Session - Target derived from current session context
- Fallback - Target resolved from allowlist or directory
- Allowlist - Target normalized from allowlist entry
- Directory - Target resolved from contacts directory
Resolution Order
For different send paths:
| Path | Resolution Priority |
|---|---|
CLI with --target |
Explicit → Validate → Send |
| Tool call | Explicit → Session → Fallback |
| Heartbeat | Explicit → Automation Recipients → Allowlist[0] |
| System Event | Requires explicit target (no fallback) |
Logging
All target resolution is logged with source and method:
[send] source=cli channel=whatsapp target=+165***1234 resolvedFrom=explicit
Request Logging (FIX-2.2)
Every send operation is logged with full context:
Log Format
[send] source=cli|rpc|session|sub-agent|tool sessionKey=xxx channel=whatsapp target=+xxx resolvedFrom=explicit|session|fallback
Logged Fields
| Field | Description |
|---|---|
| source | Origin of the send request |
| sessionKey | Session key if applicable |
| channel | Target channel (whatsapp, telegram, etc.) |
| target | Target recipient (masked for privacy) |
| resolvedTarget | Final resolved target if different |
| resolvedFrom | How the target was resolved |
| accountId | Channel account used |
| dryRun | Whether this was a dry-run |
| firstTime | Whether this is a first-time recipient |
First-Time Recipient Warnings (FIX-3.1)
Purpose
Provides visibility when automation sends to a new recipient for the first time, even if they're in the allowlist.
Behavior
When sending to a recipient not previously contacted:
- Warning is logged:
[whatsapp] First-time recipient: +165***1234 (in allowlist) - The send proceeds normally (not blocked)
- Recipient is recorded for future reference
Storage
Known recipients are tracked in:
~/.clawdbot/known-recipients.json
Log Output
[outbound/known-recipients] New recipient recorded: whatsapp:+165***1234
[outbound/known-recipients] [whatsapp] First-time recipient: +165***1234 (in allowlist)
Dry-Run Mode (FIX-3.3)
Purpose
Prevents actual message sends during development and testing.
Enabling
Environment Variable:
export CLAWDBOT_DRY_RUN=true
clawdbot gateway start
CLI Flag:
clawdbot message send --target +1234 --message "test" --dry-run
Behavior
When dry-run is enabled:
- All outbound sends are logged but not executed
- Log format:
[dry-run] would send to +xxx: message preview... - API returns success with
dryRun: truein response - No actual messages are delivered
Log Output
[outbound/dry-run] [dry-run] would send to +165***1234 channel=whatsapp source=cli message="Hello world"
Best Practices
For Operators
- Configure tight allowlists - Only include numbers that should receive messages
- Use automation.recipients - Separate interactive contacts from automation targets
- Enable dry-run for development - Set
CLAWDBOT_DRY_RUN=truewhen testing - Monitor first-time recipient warnings - Review logs for unexpected new contacts
- Review request logs - Audit
[send]log entries periodically
For Sub-Agent Development
- Use sessions_send - Route messages through parent session context
- Don't call clawdbot message send directly - It will be blocked
- Specify explicit targets - Don't rely on implicit routing
- Handle blocked sends gracefully - Catch and log errors
For Automation
- Always specify --target and --channel - Never rely on defaults
- Use automation.recipients - Configure explicit automation targets
- Test with dry-run - Verify behavior before enabling real sends
- Log all send attempts - Maintain audit trail
Security Incident Response
If an unauthorized send occurs:
- Check request logs - Find
[send]entries around the incident time - Review source field - Identify what triggered the send
- Check session key - Trace to the originating session
- Audit target resolution - Verify how the target was resolved
- Review known-recipients.json - Check if recipient was previously known
Related Configuration
{
"channels": {
"whatsapp": {
"allowFrom": ["..."],
"automation": {
"recipients": ["..."]
}
}
},
"agents": {
"defaults": {
"subagents": {
"allowDirectMessageSend": false
},
"heartbeat": {
"requireExplicitTarget": true
}
}
}
}
Environment Variables
| Variable | Description |
|---|---|
CLAWDBOT_DRY_RUN |
Enable dry-run mode (true/1/yes) |
CLAWDBOT_STATE_DIR |
Location for known-recipients.json |
Last updated: 2026-01-25