- Repository: https://github.com/clawdbot/clawdbot
- Clawdbot Version: 2026.1.24-0
- Analysis Date: 2026-01-25
- Validation Date: 2026-01-25
- Research Method: Octocode Research Agents
Analysis identified 18 verified findings in the clawdbot codebase:
- Plugin system grants unrestricted system access (by design)
- WhatsApp messages (content, location, contacts) sent to external AI providers
Validation: ✅ CONFIRMED
WhatsApp messages flow to external AI providers with user data included.
┌─────────────────────────────────────────────────────────────────────────────┐
│ WHATSAPP MESSAGE → AI PROVIDER FLOW │
└─────────────────────────────────────────────────────────────────────────────┘
STEP 1: WhatsApp Message Reception
┌──────────────────────────────────────────────────────────────────────────┐
│ src/web/inbound/monitor.ts:314 │
│ sock.ev.on("messages.upsert", handleMessagesUpsert) │
│ │
│ Baileys library receives raw WhatsApp message, creates: │
│ WebInboundMessage = { │
│ body, // Full message text │
│ senderE164, // Phone number (+1234567890) │
│ senderName, // WhatsApp display name │
│ location, // GPS coordinates + address │
│ mediaPath, // Downloaded media file path │
│ groupParticipants // All group member JIDs │
│ } │
└──────────────────────────────────────────────────────────────────────────┘
↓
STEP 2: Message Debouncing
┌──────────────────────────────────────────────────────────────────────────┐
│ src/auto-reply/inbound-debounce.ts:37 │
│ createInboundDebouncer().enqueue(inboundMessage) │
│ │
│ Batches rapid messages from same sender → onFlush() triggers │
└──────────────────────────────────────────────────────────────────────────┘
↓
STEP 3: Message Handler Routing
┌──────────────────────────────────────────────────────────────────────────┐
│ src/web/auto-reply/monitor.ts:160 │
│ createWebOnMessageHandler() → processMessage() │
│ │
│ src/web/auto-reply/monitor/process-message.ts:258-291 │
│ Builds MsgContext with ALL user data: │
│ - Body, RawBody, CommandBody │
│ - From, To, SenderE164, SenderName │
│ - LocationLat, LocationLon, LocationAddress │
│ - MediaPath, MediaType, MediaTypes │
│ - GroupSubject, groupParticipants │
│ - ReplyToBody (quoted message content) │
└──────────────────────────────────────────────────────────────────────────┘
↓
STEP 4: Reply Dispatcher Chain
┌──────────────────────────────────────────────────────────────────────────┐
│ src/auto-reply/reply/provider-dispatcher.ts:12 │
│ dispatchReplyWithBufferedBlockDispatcher() │
│ ↓ │
│ src/auto-reply/reply/dispatch-from-config.ts:267 │
│ await getReplyFromConfig(ctx, {...}) │
│ ↓ │
│ src/auto-reply/reply/get-reply.ts:25 │
│ runPreparedReply() │
└──────────────────────────────────────────────────────────────────────────┘
↓
STEP 5: Agent Execution
┌──────────────────────────────────────────────────────────────────────────┐
│ src/auto-reply/reply/agent-runner.ts:35 │
│ runReplyAgent() → runAgentTurnWithFallback() │
│ ↓ │
│ src/agents/pi-embedded-runner/run/attempt.ts:489 │
│ │
│ Uses @mariozechner/pi-ai library: │
│ activeSession.agent.streamFn = streamSimple │
│ │
│ ★ THIS IS WHERE USER DATA LEAVES THE SYSTEM ★ │
│ Full MsgContext (messages array) sent via HTTPS to: │
└──────────────────────────────────────────────────────────────────────────┘
↓
STEP 6: External AI Providers (Third-Party)
┌──────────────────────────────────────────────────────────────────────────┐
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
│ │ ANTHROPIC │ │ OPENAI │ │ GOOGLE GEMINI │ │
│ │ api.anthropic │ │ api.openai.com │ │ generativelang- │ │
│ │ .com │ │ │ │ uage.google.com │ │
│ └─────────────────┘ └─────────────────┘ └─────────────────┘ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ AWS BEDROCK │ │ OPENROUTER │ │
│ │ bedrock-runtime │ │ openrouter.ai │ │
│ │ .amazonaws.com │ │ │ │
│ └─────────────────┘ └─────────────────┘ │
│ │
│ DATA RECEIVED BY AI PROVIDERS: │
│ • Full WhatsApp message text │
│ • Sender phone number (E.164 format) │
│ • GPS location coordinates + street address │
│ • Media file contents (if media understanding enabled) │
│ • Group participant phone numbers │
│ • Conversation history (session context) │
└──────────────────────────────────────────────────────────────────────────┘
Validation Method: Traced using LSP call hierarchy and source code analysis on cloned repository.
| Data Type | Field | Example |
|---|---|---|
| Phone Number | senderE164 | +1234567890 |
| Message Content | Body, RawBody | Full message text |
| GPS Location | LocationLat, LocationLon | 37.7749, -122.4194 |
| Address | LocationName, LocationAddress | 123 Main St, City |
| Media | MediaPath, MediaType | /tmp/media/image.jpg |
| Group Participants | groupParticipants | All participant JIDs |
| Reply Context | ReplyToBody | Content of quoted message |
| Step | File | Lines | GitHub Link |
|---|---|---|---|
| Socket Connection | src/web/session.ts |
makeWASocket() | View |
| Message Handler | src/web/auto-reply/monitor/on-message.ts |
17+ | View |
| Data Structure | src/web/inbound/types.ts |
WebInboundMessage | View |
| Context Build | src/web/auto-reply/monitor/process-message.ts |
258-291 | View |
| Location Data | src/channels/location.ts |
55-74 | View |
| AI Execution | src/agents/pi-embedded-runner/run/attempt.ts |
440-500 | View |
Validation: ✅ CONFIRMED
WhatsApp session credentials stored as unencrypted JSON files.
// src/web/auth-store.ts:~15
export function resolveWebCredsPath(authDir: string): string {
return path.join(authDir, "creds.json"); // PLAINTEXT
}GitHub: src/web/auth-store.ts
Files:
creds.json- Main credentialssession-*.json- Session keyspre-key-*.json- Signal protocol keys
Validation: ✅ CONFIRMED | Status: By Design (Documented)
Validation Note: Actual location is
src/plugins/loader.ts:142-144(code restructured from claimed ~286)
Plugins execute with full system privileges. Any installed plugin can:
- Execute arbitrary shell commands
- Read/write any file
- Access network
- Access all API keys and credentials
// src/plugins/loader.ts:142-144
mod = jiti(candidate.source) // Direct code execution, no isolationGitHub: src/plugins/loader.ts
Validation: ✅ CONFIRMED
Plugin runtime exposes runCommandWithTimeout().
// src/plugins/runtime/index.ts - imports runCommandWithTimeout
import { runCommandWithTimeout } from "../../process/exec.js";
// src/process/exec.ts:~56
spawn(argv[0], argv.slice(1))GitHub: src/plugins/runtime/index.ts | src/process/exec.ts
| # | Finding | Location | Details | GitHub |
|---|---|---|---|---|
| 1 | Message content logged | src/web/inbound/monitor.ts:263-268 |
Full messages in JSON logs | View |
| 2 | Phone numbers in logs | src/web/outbound.ts:66-67 |
JID with phone digits logged | View |
| 3 | eval() in browser automation | src/browser/pw-tools-core.interactions.ts:227 |
new Function() with eval() inside |
View |
| 4 | No plugin code signing | src/plugins/loader.ts |
No integrity verification | View |
| 5 | Weak UUID fallback | ui/src/ui/uuid.ts |
Math.random() when crypto unavailable |
View |
| 6 | Hardcoded API key | extensions/copilot-proxy/index.ts:3 |
DEFAULT_API_KEY = "n/a" (placeholder) |
View |
| 7 | Postinstall modifies git config | scripts/setup-git-hooks.js:53 |
git config core.hooksPath |
View |
| 8 | Patch injection vector | scripts/postinstall.js:266-276 |
Unsanitized patch paths from package.json | View |
| 9 | Incomplete shell metachar blocking | src/infra/exec-safety.ts:1 |
Missing (){}[]!#*? characters |
View |
| 10 | Security bypass with "full" elevation | src/agents/bash-tools.exec.ts:842 |
ask = "off" when elevatedMode=full |
View |
| 11 | SHA-1 hash usage | src/infra/gateway-lock.ts:136 |
createHash("sha1") |
View |
| 12 | TOCTOU race in media server | src/media/server.ts:10-31 |
lstat → realpath → stat → readFile race | View |
| 13 | Prototype pollution risk | ui/src/ui/gateway.ts:226 |
JSON.parse() on WebSocket data unsanitized |
View |
| 14 | Session keys in environment variables | src/infra/provider-usage.fetch.claude.ts:15-16 |
CLAUDE_AI_SESSION_KEY in env |
View |
| Control | Description |
|---|---|
| SSRF Protection | Blocks private IPs and metadata endpoints |
| Path Traversal Protection | Validates paths and rejects symlinks |
| Credential Redaction | Filters API keys from logs |
| Exec Safety Checks | Blocks some shell metacharacters (partial) |
| Security Audit Tool | Built-in clawdbot security audit --deep |
Two primary findings (both validated):
-
Plugin Trust Model - Installing any plugin grants complete system access (documented behavior) - ✅ CONFIRMED via
jiti()atsrc/plugins/loader.ts:142-144andrunCommandWithTimeoutexport atsrc/plugins/runtime/index.ts:107-109 -
WhatsApp Data Flow - Messages including content, phone numbers, location, and group participants flow to external AI providers (Anthropic, OpenAI, Google, AWS) - ✅ CONFIRMED via full data flow trace from socket to AI provider
| Issue | Claimed | Actual |
|---|---|---|
| Plugin loader jiti() | ~286 | 142-144 |
| SHA-1 usage | unspecified | 136 |
| TOCTOU race | 24 | 10-31 |
| Session keys | 21 | 15-16 |
| Gateway JSON.parse | 233 | 226 |
Research conducted using Octocode Research Agents. All findings verified against clawdbot v2026.1.24-0 source code.
Validation conducted 2026-01-25 using parallel GitHub code analysis.