Back to skill

Security audit

Whatsapp Memory

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent WhatsApp memory helper, but it persistently stores sensitive chat context and includes unsafe file/path handling that can exceed its intended memory scope.

Review before installing. Use only if you are comfortable storing WhatsApp conversation memory on disk, and harden it first for real use: allowlist memory filenames, strictly validate or encode conversation IDs, treat recalled memory as untrusted data, avoid logging sensitive personal information, and define deletion/retention rules.

Vulnerability Patterns
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • 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
  • 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 (3)

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:84
Finding
Arbitrary File Creation and Append via Unvalidated File Name<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 84-105 **Vulnerability Type**: Path traversal and arbitrary file write **Risk Level**: High ### Vulnerable Code ```bash wa_log() { TYPE="$1" # "group" or "dm" ID="$2" # JID or phone CONTENT="$3" # what to log FILE_NAME="${4:-context.md}" # context.md / decisions.md / notes.md # Sanitize ID SAFE_ID=$(echo "$ID" | tr '@.+' '---') BASE="$HOME/.openclaw/workspace/memory/whatsapp" # Pick the right directory if [ "$TYPE" = "group" ]; then FILE="$BASE/groups/$SAFE_ID/$FILE_NAME" else FILE="$BASE/dms/$SAFE_ID/$FILE_NAME" fi # Create file if missing if [ ! -f "$FILE" ]; then mkdir -p "$(dirname "$FILE")" touch "$FILE" fi # Append timestamped entry echo "[$(date -u +%Y-%m-%d\ %H:%M)] $CONTENT" >> "$FILE" } ``` ### Technical Analysis The fourth argument to `wa_log`, `FILE_NAME`, is used directly when constructing the destination path. Although comments describe an intended set of files such as `context.md`, `decisions.md`, and `notes.md`, the implementation does not enforce this allowlist. A caller can supply directory traversal components such as `../../`, or an absolute path. In shell path resolution, an absolute `FILE_NAME` does not necessarily discard the preceding string when concatenated this way, but traversal components can still escape the intended conversation directory. The subsequent `mkdir -p`, `touch`, and append redirection create or modify the resolved destination. The appended content is also caller-controlled. This turns a conversation-memory helper into a general file-append primitive within the operating-system account's writable filesystem. ### Attack Path 1. An attacker or compromised calling workflow influences the fourth argument passed to `wa_log`. 2. The attacker supplies a traversal path, for example: ```bash wa_log "dm" "+123456789" "attac ...[truncated 1095 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace the free-form filename with an exact allowlist: ```bash case "$TYPE:$FILE_NAME" in group:context.md|group:decisions.md|group:people.md) ;; dm:context.md|dm:notes.md) ;; *) echo "Invalid memory file" >&2 return 1 ;; esac ``` 2. Reject filenames containing `/`, `\`, `..`, control characters, or leading path separators. 3. Canonicalize both the base directory and destination, then verify that the destination remains beneath the expected conversation directory. 4. Do not create arbitrary parent directories from user-provided path components. 5. Give the memory directory restrictive permissions, such as `0700` for directories and `0600` for files. 6. Treat `CONTENT` as untrusted data and ensure that memory files are never subsequently executed or sourced as shell code. 7. Add tests covering traversal strings, absolute paths, symbolic links, control characters, and invalid filenames. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:124
Finding
Python Code Injection Through Unsafe Conversation Identifier Interpolation<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 124-150 **Vulnerability Type**: Code injection caused by dynamic source-code construction **Risk Level**: High ### Vulnerable Code ```bash wa_context() { TYPE="$1" ID="$2" LINES="${3:-20}" # Sanitize ID SAFE_ID=$(echo "$ID" | tr '@.+' '---') BASE="$HOME/.openclaw/workspace/memory/whatsapp" # Pick directory if [ "$TYPE" = "group" ]; then DIR="$BASE/groups/$SAFE_ID" else DIR="$BASE/dms/$SAFE_ID" fi # Check if memory exists if [ ! -d "$DIR" ]; then echo "No memory for this conversation yet." return fi # Read the conversation name from meta.json NAME=$(python3 -c " import json with open('$DIR/meta.json') as f: print(json.load(f).get('name', '?')) " 2>/dev/null || echo "?") ``` ### Technical Analysis The identifier sanitization only replaces `@`, `.`, and `+`: ```bash SAFE_ID=$(echo "$ID" | tr '@.+' '---') ``` It does not reject single quotes, newlines, path separators, control characters, or other characters meaningful in Python source. The resulting directory path is interpolated directly into a Python program supplied through `python3 -c`: ```python with open('$DIR/meta.json') as f: ``` Because `$DIR` becomes part of Python source code rather than being passed as data, a crafted identifier containing a quote and suitable line structure can terminate the string literal and introduce additional Python statements. Newlines can be used to account for the surrounding `with` statement and remaining generated source. The same unsafe source-construction pattern also appears in the search functionality around lines 174-178. The principal directly reachable instance is in `wa_context`, which the skill instructs the agent to invoke for every incoming message. The directory existence check does not eliminate the vulnerability. An attacker who can cause a correspondingly named directory to exist, or who combines this weakness with the unsafe p ...[truncated 1311 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Never insert filesystem paths or identifiers into dynamically generated Python source. 2. Pass the path as an ordinary argument: ```bash NAME=$(python3 - "$DIR/meta.json" <<'PY' import json import sys with open(sys.argv[1], encoding="utf-8") as f: print(json.load(f).get("name", "?")) PY ) ``` 3. Strictly validate identifiers using an allowlist appropriate for WhatsApp JIDs and phone numbers. Reject all newlines, control characters, quotes, path separators, and unexpected syntax. 4. Use a non-lossy identifier encoding, such as URL-safe Base64 or a cryptographic hash, for directory names instead of partial character replacement. 5. Validate `TYPE` against only `group` and `dm`; reject all other values. 6. Apply the same correction to the Python invocation in `wa_search` and any other location that constructs Python source from paths. 7. Add security tests using identifiers containing quotes, newlines, backslashes, slashes, Unicode control characters, and traversal components. ]]>

T02 · Agent Memory Poisoning

Warning
Location
SKILL.md:101
Finding
Persistent Agent Memory Poisoning Through Untrusted Conversation Content<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 101-105 and 214-224 **Vulnerability Type**: Persistent untrusted-memory poisoning **Risk Level**: Medium ### Vulnerable Code and Instructions ```bash # Append timestamped entry echo "[$(date -u +%Y-%m-%d\ %H:%M)] $CONTENT" >> "$FILE" ``` ```text On every incoming message: 1. Extract JID or phone from inbound metadata 2. If group: run wa_context "group" "$JID" 10 If DM: run wa_context "dm" "$PHONE" 10 3. Use context to inform your response 4. After responding: log anything worth remembering ``` ### Technical Analysis Conversation-derived `CONTENT` is persisted in Markdown files without structured provenance, trust labels, instruction filtering, review, expiration, or separation between factual data and executable agent instructions. The workflow then directs the agent to load this persisted content for every incoming message and use it to inform its response. Consequently, instruction-like text originating from an untrusted participant can survive beyond the original conversation and repeatedly influence future model sessions. The skill advises against storing credentials, but it does not tell the agent to treat recalled text strictly as untrusted data or to disregard commands embedded in memory. It also does not require that saved entries be transformed into constrained, agent-generated factual summaries. ### Attack Path 1. A participant sends adversarial text framed as a decision, preference, task, participant note, or other information that meets the skill's logging criteria. 2. The agent determines that the text is worth remembering. 3. `wa_log` appends the content to a persistent conversation memory file. 4. The original model session ends, but the stored entry remains on disk. 5. On a later message, the workflow invokes `wa_context`. 6. The poisoned entry is returned as conversation context. 7. The agent interprets the recalled instruction-like content as relevant guidan ...[truncated 838 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Store constrained, agent-generated factual summaries instead of raw participant text. 2. Use a structured schema with fields such as source, timestamp, author, confidence, category, expiration, and trust level. 3. Explicitly instruct the agent that recalled memory is untrusted reference data and that commands or policy statements found in memory must never be followed as instructions. 4. Separate factual records from operational instructions. Do not allow conversation content to create persistent agent rules. 5. Require confirmation or human review before persisting high-impact preferences, permissions, identity claims, or instructions. 6. Detect and reject prompt-injection patterns when creating memory entries. 7. Apply expiration, deduplication, correction, and deletion mechanisms. 8. Preserve provenance when displaying context so the model can distinguish participant statements from verified facts. 9. Limit memory retrieval to the minimum relevant records rather than automatically injecting recent free-form text into every response. 10. Ensure searches, digests, and backups retain trust labels and do not merge untrusted content into higher-trust system or owner instructions. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (3)

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill persistently logs WhatsApp conversation content, names, phone numbers, group identifiers, and notes to local files, but provides only a narrow warning not to log secrets or credentials. In practice, normal chat context often contains personal or sensitive information, so this design can lead to unbounded retention of private data without clear consent, minimization, retention, or access-control guidance.

Description-Behavior Mismatch

Medium
Confidence
89% confidence
Finding
The manifest describes conversation-scoped memory for groups and DMs, emphasizing separate contexts and preventing context bleed between chats. However, `wa_search` searches across the entire WhatsApp memory store, and the weekly digest later aggregates entries from all group and DM directories, which expands the behavior from per-conversation memory management to cross-conversation analytics and retrieval.

Description-Behavior Mismatch

Low
Confidence
80% confidence
Finding
The manifest positions the skill as a file-based WhatsApp memory utility for storing and recalling conversation context. The 'Loop Prevention Rules' section goes beyond memory handling and prescribes operational behavior about when to reply, duplicate-send suppression, and coordination among multiple assistants, which is outside the stated memory-only scope.

Static analysis

No suspicious patterns detected.