Back to skill

Security audit

WhatsApp Utils

Security checks for vulnerabilities and agentic risk

Overview

This WhatsApp utility is mostly coherent, but its contact export can expose an entire local contact list without a warning or confirmation step.

Review before installing if your OpenClaw WhatsApp state contains real contacts. Only run export-contacts when you intentionally want the full local contact list printed into the agent output, and prefer adding an explicit confirmation flag, filtering, or redaction before routine use.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/utils.js:93
Finding
WhatsApp Contact PII Exposed Through Standard Output<![CDATA[ ## Vulnerability Details **File Location**: `scripts/utils.js:93-108` **Vulnerability Type**: Sensitive data exposure through logs and command output **Risk Level**: Medium ### Vulnerable Code ```javascript function exportContacts() { try { const contactsPath = path.join(CREDS_PATH, 'contacts.json'); if (!fs.existsSync(contactsPath)) { console.log(JSON.stringify({ error: 'Contacts file not found' })); return; } const contacts = JSON.parse(fs.readFileSync(contactsPath, 'utf8')); const exported = Object.entries(contacts) .filter(([id]) => id.endsWith('@s.whatsapp.net')) .map(([id, c]) => ({ phone: id.replace('@s.whatsapp.net', ''), name: c.name || c.notify || null, isBusiness: c.isBusiness || false })); console.log(JSON.stringify({ total: exported.length, contacts: exported }, null, 2)); } catch (error) { console.log(JSON.stringify({ error: error.message })); } } ``` ### Technical Analysis The `export-contacts` command reads `contacts.json` from the OpenClaw WhatsApp credential-state directory and prints the entire contact list to standard output. The disclosed fields include telephone numbers, contact names, and business-account status. Although exporting contacts is an advertised feature, returning the complete dataset through standard output creates a secondary disclosure channel. Output from agent-executed commands may be incorporated into conversation history, execution traces, monitoring systems, CI logs, or other records with broader access and longer retention than the source credential directory. The implementation does not request explicit confirmation, support record selection, redact sensitive fields, or restrict the volume of personal data returned. ### Attack Path 1. The attacker or an untrusted workflow obtains the ability to invoke this skill in a context that can access the user's OpenClaw state directory. 2. The attacker invokes `node scr ...[truncated 1177 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Require explicit user confirmation immediately before exporting contact data, including a clear description of the fields and number of records that will be exposed. 2. Avoid returning full contact records through standard output by default. Return only a count or a redacted preview unless the user explicitly requests the complete export. 3. Add filtering and field-selection options so callers can export only required records and attributes. 4. If a complete export is necessary, write it to an explicitly approved destination rather than an agent transcript. Create the file with restrictive permissions such as mode `0600`. 5. Do not log exported contact content. Ensure execution and telemetry systems redact phone numbers and names. 6. Validate that the resolved state and export paths are authorized for the active user and execution context. 7. Document the privacy implications and expected retention behavior of contact exports. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
scripts/utils.js:117
Finding
Message IDs Generated with a Non-Cryptographic PRNG<![CDATA[ ## Vulnerability Details **File Location**: `scripts/utils.js:117-124` **Vulnerability Type**: Predictable identifier generation **Risk Level**: Low ### Vulnerable Code ```javascript function generateMessageId() { const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; let id = ''; for (let i = 0; i < 22; i++) { id += chars.charAt(Math.floor(Math.random() * chars.length)); } console.log(JSON.stringify({ messageId: id, fullId: `true_${id}` }, null, 2)); } ``` ### Technical Analysis The message ID generator selects each character using JavaScript's `Math.random()`. This function is designed for general-purpose pseudo-randomness and does not provide cryptographic unpredictability. If downstream automation uses these generated values as security-sensitive identifiers, deduplication keys, authenticity indicators, or values that must resist guessing, an observer may be able to exploit the weak randomness model. The code also does not verify uniqueness against existing message IDs. The immediate risk is limited because the audited project does not show how generated IDs are consumed, and no direct authentication or authorization decision based on these IDs was found. The weakness becomes exploitable when another component incorrectly treats the output as unpredictable or authoritative. ### Attack Path 1. A downstream workflow uses `gen-id` output as a message identifier with security or integrity significance. 2. An attacker observes one or more generated identifiers or otherwise obtains information about the runtime's pseudo-random sequence. 3. The attacker attempts to predict future values or produce colliding identifiers. 4. The attacker submits a predicted or duplicate identifier to the dependent workflow. 5. If that workflow trusts identifier uniqueness or secrecy without independent validation, the attacker may cause message confusion, incorrect deduplication, spoofed references, or integrity failures. No direct privilege escalati ...[truncated 648 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace `Math.random()` with Node.js cryptographic randomness from the built-in `crypto` module. 2. Generate unbiased character indexes with `crypto.randomInt()`: ```javascript const crypto = require('crypto'); function generateMessageId() { const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; let id = ''; for (let i = 0; i < 22; i++) { id += chars[crypto.randomInt(chars.length)]; } console.log(JSON.stringify({ messageId: id, fullId: `true_${id}` }, null, 2)); } ``` 3. If strict WhatsApp protocol compatibility is required, use the identifier-generation mechanism defined by the relevant supported client library instead of creating a synthetic approximation. 4. Enforce uniqueness in the storage or message-processing layer rather than relying solely on randomness. 5. Document that generated IDs are synthetic and must not be used as authentication tokens, secrets, or authorization controls. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (4)

Lp3

Medium
Category
MCP Least Privilege
Confidence
85% confidence
Finding
The skill documents execution of a Node.js script via exec but does not declare any explicit tool scope or permissions boundaries in the skill metadata. This creates ambiguity about what runtime capabilities are intended and can allow a broader-than-necessary execution environment, increasing the risk of misuse or unintended access to environment data.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The skill exposes an export-contacts command, which implies bulk access to potentially sensitive personal data, but provides no warning, consent requirement, or description of privacy implications. In the context of a WhatsApp automation utility, contact data is especially sensitive because it may include personally identifiable information and relationship metadata.

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
The code automatically prepends country code `55` when the number length matches local formats, and the comment states this defaults to Brazil. This imposes a locale-specific behavior without user opt-in or a documented regional constraint, which can violate language/locale policy expectations.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The `export-contacts` command reads `contacts.json` from the WhatsApp credential store and prints a full list of phone numbers, names, and business flags to stdout with no consent check, access control, masking, or warning. In an agent skill context, this creates a real privacy and data-exposure risk because invoking the utility can exfiltrate personal contact data from a local WhatsApp cache into logs, downstream tools, or user-visible output.

Static analysis

No suspicious patterns detected.