Back to skill

Security audit

WhatsApp Lead Hunter

Security checks for vulnerabilities and agentic risk

Overview

The skill is coherent but needs Review because it automates scraped-contact WhatsApp outreach and includes an unsafe batch sender that can expose credentials or run unintended code.

Review this before installing. Use it only with legally obtained contacts and proper opt-out/consent handling. Do not run the batch sender with untrusted lead filenames, do not pass real WAHA keys on the command line, prefer dry-run first, restrict WAHA to trusted local or HTTPS endpoints, and define how scraped phone numbers and ignore lists will be retained or deleted.

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

Error
Location
scripts/batch_send.sh:58
Finding
Arbitrary Python Code Execution Through Unsafely Interpolated Lead File Path<![CDATA[ ## Vulnerability Details **File Location**: `scripts/batch_send.sh`, lines 58-70 **Vulnerability Type**: Python source-code injection **Risk Level**: High ### Vulnerable Code ```bash # Count leads TOTAL=$(python3 -c "import json; print(len(json.load(open('$LEADS'))))") echo "📋 $TOTAL leads loaded from $LEADS" echo "⏱️ Delay: ${DELAY}s between messages" echo "📡 WAHA: $WAHA_URL (session: $SESSION)" [ "$DRY_RUN" = true ] && echo "🔍 DRY RUN MODE — no messages will be sent" echo "" SENT=0 FAILED=0 # Process each lead python3 -c " import json, sys leads = json.load(open('$LEADS')) ``` ### Technical Analysis The user-controlled `--leads` value is interpolated directly into source code passed to `python3 -c`. Shell quoting prevents the shell from immediately interpreting the value, but it does not escape the value for use inside a Python string literal. A filename containing a single quote and additional Python syntax can terminate the intended string and insert statements into either Python invocation. The earlier file-existence check does not prevent exploitation because Unix filenames may legally contain quote characters, semicolons, parentheses, and other characters useful for constructing valid Python syntax. This exceeds the privileges needed to read a JSON file. The path should be treated solely as data, but the implementation allows it to alter executable Python source. ### Attack Path 1. An attacker creates or distributes a JSON leads file whose filename contains Python syntax, or convinces the operator to invoke the script with an attacker-selected path. 2. The operator runs `batch_send.sh --leads <attacker-controlled-path> --waha-key <key>`. 3. The `-f` check succeeds because a file exists under the crafted name. 4. The shell expands `$LEADS` inside the double-quoted `python3 -c` argument. 5. Embedded quote characters terminate the Python string passed to `open()`, and the remaining filename content is parsed as Python statements. 6. ...[truncated 961 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Never construct Python source code using shell-controlled values. Pass the path as a positional argument: ```bash TOTAL=$(python3 -c \ 'import json, sys; print(len(json.load(open(sys.argv[1], encoding="utf-8"))))' \ "$LEADS") ``` Replace the second invocation similarly: ```bash python3 - "$LEADS" <<'PY' | import json import sys with open(sys.argv[1], encoding="utf-8") as file: leads = json.load(file) for lead in leads: name = lead.get("name", "Unknown") phone = ( lead.get("phone", "") .replace("+", "") .replace(" ", "") .replace("-", "") ) if phone: print(f"{phone}|{name}") PY while IFS='|' read -r PHONE NAME; do # Existing processing logic : done ``` Additional hardening should include: 1. Validate that the decoded JSON root is an array and that each entry is an object. 2. Validate phone numbers against a strict numeric format and reasonable length. 3. Reject files larger than an operationally necessary limit. 4. Avoid parsing structured records through a delimiter such as `|`, since lead names can contain that character; use a safer structured transport or null-delimited records. 5. Add regression tests using paths containing spaces, quotes, newlines, shell metacharacters, and Python syntax. 6. Run the script as an unprivileged account with access limited to the required lead files and WAHA endpoint. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/batch_send.sh:44
Finding
WAHA API Key Exposed Through Command-Line Arguments<![CDATA[ ## Vulnerability Details **File Location**: `scripts/batch_send.sh`, lines 44-47 **Vulnerability Type**: Sensitive credential exposure through process arguments **Risk Level**: Medium ### Vulnerable Code ```bash if [ -z "$LEADS" ] || [ -z "$WAHA_KEY" ]; then echo "Usage: batch_send.sh --leads FILE --waha-key KEY [--message MSG] [--delay SECS]" exit 1 fi ``` The key is populated from a command-line argument at line 31: ```bash --waha-key) WAHA_KEY="$2"; shift 2 ;; ``` The documented invocation also directs users to expose the key this way: ```bash scripts/batch_send.sh \ --leads leads/usak/veteriner.json \ --template references/pitch-templates.md \ --sector veteriner \ --waha-url http://localhost:3000 \ --waha-key YOUR_KEY \ --delay 120 \ --ignore-file data/outreach_ignore_lids.txt ``` ### Technical Analysis The script requires the WAHA API key to be supplied as `--waha-key KEY`. Command-line arguments can be recorded or exposed through: - Process inspection tools such as `ps`. - Operating-system process metadata such as `/proc/<pid>/cmdline`, subject to local access controls. - Shell history. - Job-control, monitoring, auditing, and orchestration systems. - Diagnostic logs that record command invocations. The exposure window can be lengthy because the script intentionally sleeps between messages. The documentation states that the key may be passed as a parameter or environment variable, but the implementation does not initialize the key from an environment variable. The key is also placed in the `curl` header argument during each request: ```bash -H "X-Api-Key: $WAHA_KEY" ``` This creates additional, shorter process-metadata exposure while each `curl` process is active. ### Attack Path 1. An operator starts a batch using `--waha-key <secret>`. 2. The batch remains active while sending messages and sleeping between recipients. 3. A local user, monitoring agent, support utility, or process with sufficient process-inspect ...[truncated 1129 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Remove the requirement to pass secrets through command-line arguments. Prefer a protected environment variable or a secret file descriptor: ```bash WAHA_KEY="${WAHA_KEY:-}" if [ -z "$LEADS" ] || [ -z "$WAHA_KEY" ]; then echo "Usage: WAHA_KEY=... batch_send.sh --leads FILE [--message MSG] [--delay SECS]" exit 1 fi ``` For stronger protection, support a key file with restrictive permissions: ```bash if [ -n "${WAHA_KEY_FILE:-}" ]; then [ -f "$WAHA_KEY_FILE" ] || { echo "WAHA key file not found" >&2 exit 1 } WAHA_KEY=$(cat -- "$WAHA_KEY_FILE") fi ``` Additional hardening should include: 1. Deprecate and then remove `--waha-key`. 2. Update `SKILL.md` examples so they never place a real key in command arguments. 3. Read secrets from a dedicated secret manager when used in CI or orchestration environments. 4. Restrict WAHA keys to the minimum API permissions required for sending text. 5. Restrict the WAHA listener to trusted interfaces and clients. 6. Prefer HTTPS for non-loopback WAHA URLs to prevent network interception. 7. Rotate any key that has previously appeared in command history or logs. 8. Ensure diagnostic output never prints request headers or secret values. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (10)

External Script Fetching

High
Category
Supply Chain
Content
if [ "$DRY_RUN" = true ]; then
    echo "[$SENT/$TOTAL] 📝 Would send to $NAME ($PHONE)"
  else
    RESULT=$(curl -s -X POST "$WAHA_URL/api/sendText" \
      -H "X-Api-Key: $WAHA_KEY" \
      -H "Content-Type: application/json" \
      -d "{\"session\": \"$SESSION\", \"chatId\": \"${PHONE}@c.us\", \"text\": $(echo "$MSG" | python3 -c 'import json,sys; print(json.dumps(sys.stdin.read()))')}" 2>/dev/null)
Confidence
90% confidence
Finding
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill clearly instructs use of shell-based capabilities via curl and scripts/batch_send.sh, yet it declares no allowed tool scope or permissions. This creates an authorization gap where an agent may execute networked shell actions without explicit user-visible restriction, increasing the chance of unintended message sending or misuse.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The skill is designed to scrape business contact details, store them locally, profile businesses, and send cold WhatsApp outreach, but it provides no consent, retention, lawful-basis, or privacy notice guidance. That omission makes unauthorized collection, processing, and messaging of personal or business contact data much more likely, with legal, compliance, and reputational consequences.

External Transmission

Medium
Category
Data Exfiltration
Content
### 4. Send via WAHA

```bash
curl -X POST "http://localhost:3000/api/sendText" \
  -H "X-Api-Key: YOUR_WAHA_KEY" \
  -H "Content-Type: application/json" \
  -d '{
Confidence
92% confidence
Finding
The skill includes a concrete example for transmitting personalized outreach messages and recipient identifiers to an HTTP API endpoint. Even though the target is localhost, this is still external transmission from the agent context to another service and can enable unauthorized messaging, data leakage to an improperly secured local service, or abuse if the endpoint is exposed or proxied.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The veterinary template explicitly promotes automated reminders, customer records, and animal/patient-related data handling without any mention of consent, lawful basis, retention, or privacy safeguards. In a lead-generation and WhatsApp outreach skill, this omission can encourage users to deploy workflows that process personal and potentially sensitive data in ways that violate privacy expectations or regulations.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The dental clinic template discusses patient history, recall reminders, and promotional outreach tied to dental services, but provides no warning about privacy, confidentiality, consent, or health-data handling. Because this skill is designed for automated WhatsApp marketing and operational messaging, it materially increases the chance of unsafe processing or disclosure of sensitive health-related information.

External Transmission

Medium
Category
Data Exfiltration
Content
if [ "$DRY_RUN" = true ]; then
    echo "[$SENT/$TOTAL] 📝 Would send to $NAME ($PHONE)"
  else
    RESULT=$(curl -s -X POST "$WAHA_URL/api/sendText" \
      -H "X-Api-Key: $WAHA_KEY" \
      -H "Content-Type: application/json" \
      -d "{\"session\": \"$SESSION\", \"chatId\": \"${PHONE}@c.us\", \"text\": $(echo "$MSG" | python3 -c 'import json,sys; print(json.dumps(sys.stdin.read()))')}" 2>/dev/null)
Confidence
73% confidence
Finding
The script sends phone numbers and personalized message contents to an arbitrary operator-supplied WAHA_URL without validating that the endpoint is trusted or protected by HTTPS. In a lead-generation/outreach skill handling personal contact data, this can expose recipient data to interception or to a malicious remote service if the URL is misconfigured.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The curl POST sends lead phone numbers, session identifiers, and message text to an HTTP API endpoint. Although the script logs that WAHA will be used, it does not clearly warn that personal lead data and message contents are being transmitted over the network or that the default URL is plain HTTP.

Natural-Language Policy Violations

Low
Confidence
76% confidence
Finding
The file mixes Turkish and English sector/location examples and sector labels, implying a locale-specific operating pattern, but it does not explicitly offer the user a language or locale choice for generated outreach. Because the policy applies to natural-language constraints across all file types, hardwiring locale behavior without opt-in can be a language/locale policy issue.

Missing User Warnings

Low
Confidence
88% confidence
Finding
The script persists phone numbers to the path provided by --ignore-file, which is a file write involving personal contact data. While the argument description mentions appending sent numbers, there is no explicit warning in runtime output or safety note about storing recipient identifiers on disk.

Static analysis

No suspicious patterns detected.