Skip to content

Instantly share code, notes, and snippets.

@bgauryy
Last active January 25, 2026 12:08
Show Gist options
  • Select an option

  • Save bgauryy/72b8a35d1849ad15469ba58e09428f58 to your computer and use it in GitHub Desktop.

Select an option

Save bgauryy/72b8a35d1849ad15469ba58e09428f58 to your computer and use it in GitHub Desktop.
Clawdbot Security Audit Report - A code-verified security assessment of the clawdbot WhatsApp AI assistant (v2026.1.24-0) identifying 18 security issues across critical, high, and medium severity levels. Key findings: (1) WhatsApp messages including phone numbers, GPS locations, and group contacts flow unsanitized to external AI providers (Anthr…

Clawdbot Code Analysis Report


Summary

Analysis identified 18 verified findings in the clawdbot codebase:

  1. Plugin system grants unrestricted system access (by design)
  2. WhatsApp messages (content, location, contacts) sent to external AI providers

Validated Findings

1. WhatsApp Data Flow to AI Providers

Validation: ✅ CONFIRMED

WhatsApp messages flow to external AI providers with user data included.

Data Flow (Validated via LSP + Code Tracing)

┌─────────────────────────────────────────────────────────────────────────────┐
│                    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 Sent to AI Providers

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

Code References (Verified)

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

2. WhatsApp Credentials Storage

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 credentials
  • session-*.json - Session keys
  • pre-key-*.json - Signal protocol keys

3. Plugin System - No Sandboxing

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 isolation

GitHub: src/plugins/loader.ts


4. Command Execution API

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


5. Additional Confirmed Findings

# 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

Existing Security Controls

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

Conclusion

Two primary findings (both validated):

  1. Plugin Trust Model - Installing any plugin grants complete system access (documented behavior) - ✅ CONFIRMED via jiti() at src/plugins/loader.ts:142-144 and runCommandWithTimeout export at src/plugins/runtime/index.ts:107-109

  2. 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


Validation Notes

Line Number Corrections

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment