Back to skill

Security audit

WhatsApp Local Endpoints Router

Security checks for vulnerabilities and agentic risk

Overview

This skill has a clear local WhatsApp-routing purpose, but it can upload any readable local file to a configurable endpoint and mirrors backend responses directly, so it needs review before installation.

Install only if you trust the local backend and the environment that launches this skill. Before use, restrict BASE_URL to loopback, validate that decode inputs are real WhatsApp image attachments in an approved directory, avoid passing arbitrary local paths, and do not mirror raw backend or error bodies that may contain secrets.

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 (1)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/route_whatsapp.sh:4
Finding
Arbitrary Local File Upload to a Configurable Destination## Vulnerability Details **File Location**: `scripts/route_whatsapp.sh`, lines 4–47 **Vulnerability Type**: Unrestricted local file upload and potential data exfiltration **Risk Level**: High ### Vulnerable Code ```bash BASE_URL="${BASE_URL:-http://localhost:8080}" ``` ```bash decode) if [[ -z "$ARG" ]]; then echo '{"error":"missing image path argument for decode mode"}' exit 2 fi if [[ ! -f "$ARG" ]]; then printf '{"error":"image file not found: %s"}\n' "$ARG" exit 2 fi curl --silent --show-error --max-time "$TIMEOUT" \ -X POST "$BASE_URL/decode-qr" \ -F "image=@$ARG" ;; ``` ### Technical Analysis Decode mode accepts an arbitrary local path through `ARG`. The only validation is `[[ -f "$ARG" ]]`, which confirms that the supplied path refers to a regular file. The script does not require the file to reside in an approved WhatsApp attachment directory, validate that it is an image, enforce an allowed file extension or MIME type, restrict symbolic-link resolution, or impose a file-size limit. Curl's multipart syntax, `-F "image=@$ARG"`, causes curl to read the referenced local file and transmit its contents. Therefore, any readable regular file available to the script's operating-system account can be submitted instead of a QR image. The upload destination is also configurable through the inherited `BASE_URL` environment variable. Although the default destination is loopback-only, a caller capable of controlling the execution environment can redirect the upload to an external HTTP endpoint. The combination creates a local-file disclosure and potential data-exfiltration primitive. ### Attack Path 1. An attacker influences the decode argument directly or induces the agent to treat an attacker-selected local path as an image attachment. 2. The attacker supplies a readable sensitive path, for example an application configuration or credential file. 3. The `-f` che ...[truncated 1243 chars]
Remediation
## Remediation Suggestions 1. Resolve the supplied path to its canonical absolute path and require it to remain inside a dedicated, trusted WhatsApp attachment directory. 2. Reject symbolic links or verify the canonical target after link resolution to prevent path-boundary bypasses. 3. Validate the file using an allowlist of supported image MIME types and verify its actual file signature rather than relying only on its extension. 4. Enforce conservative file-size and image-dimension limits before upload. 5. Do not inherit an unrestricted `BASE_URL`. Prefer a fixed loopback endpoint, or parse and allowlist the exact scheme, host, port, and route. 6. Reject credentials, query strings, redirects, non-HTTP schemes, and non-loopback destinations. Consider using curl's `--proto`, `--proto-redir`, and `--max-redirs 0` restrictions. 7. Run the script under a dedicated least-privileged account that cannot read application secrets or unrelated user files. 8. Pass attachment metadata through a trusted interface rather than accepting an arbitrary filesystem path from user-controlled content.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (7)

Ssd 3

High
Confidence
98% confidence
Finding
The skill explicitly instructs the agent to mirror backend response bodies and raw error bodies directly to the user. This is a direct data exfiltration path: localhost services may return internal diagnostics, secrets, stack traces, file paths, tokens, or other sensitive data that should never be reflected verbatim to an external chat user.

Lp3

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding
The skill invokes a shell script but does not declare any explicit tool scope or permissions boundary. This increases risk because a broadly triggered skill can execute local commands without transparent constraints, making review, isolation, and policy enforcement harder.

Vague Triggers

Medium
Confidence
93% confidence
Finding
The trigger conditions are extremely broad, covering ordinary WhatsApp text and even random symbols, so the skill could activate for routine conversation rather than a narrow, intended use case. In combination with shell execution and local HTTP forwarding, this broad scope raises the likelihood of unintended data routing and backend interaction.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill is designed to forward WhatsApp content to localhost services and return backend JSON directly to the user, but provides no warning or consent flow about data handling. This creates a privacy and disclosure risk because sensitive user messages, attachments, or derived backend data may be exposed or processed unexpectedly.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The manifest says plain text or random symbols should be sent to POST /process, implying the text content itself is routed. In code, process mode wraps the argument as {"number": ...}, which semantically treats the input as a phone number rather than generic message text and does not match the stated routing behavior.

External Transmission

Medium
Category
Data Exfiltration
Content
PY
)"

    curl --silent --show-error --max-time "$TIMEOUT" \
      -X POST "$BASE_URL/process" \
      -H 'Content-Type: application/json' \
      -d "$PAYLOAD"
Confidence
90% confidence
Finding
The script transmits user-supplied content to an HTTP endpoint controlled by the configurable BASE_URL variable, which can redirect data away from localhost if the environment is altered. Because the response is returned directly to the user and no validation or allowlisting is applied to BASE_URL, this creates a realistic data-exfiltration and trust-boundary risk despite the benign local-routing use case.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
In process mode, the script transmits the user-supplied argument to a remote endpoint via curl, and in decode mode it uploads a local file. While the code performs the operations directly, it does not include any confirmation, user-facing disclosure, or warning comment/docstring about this data transmission, which is relevant for a code-file missing-warning review.