Back to skill

Security audit

ManyChat CLI

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent ManyChat automation skill, but it needs Review because it can change live subscriber data, send messages, and may expose the ManyChat API key through an unrestricted API host override.

Review before installing in a production ManyChat workspace. Use a least-privilege API key, avoid --base-url and MANYCHAT_BASE_URL unless pointed to a trusted HTTPS test service with a test credential, require explicit approval before subscriber updates or sends, and verify that playbooks target only intended subscribers.

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
manychat_cli.py:36
Finding
Unrestricted API Host Override Exposes the ManyChat Bearer Token and Subscriber Data<![CDATA[ ## Vulnerability Details **File Location**: `manychat_cli.py`, lines 36-49, 122-123, and 246-251 **Vulnerability Type**: Arbitrary credential and sensitive-data transmission **Risk Level**: High ### Vulnerable Code The HTTP client constructs the destination from an unrestricted base URL and attaches the API key to every request: ```python def call(self, endpoint: str, payload: Optional[Dict[str, Any]] = None) -> Dict[str, Any]: if not endpoint.startswith("/"): endpoint = "/" + endpoint url = f"{self.base_url.rstrip('/')}{endpoint}" body = json.dumps(payload or {}).encode("utf-8") req = request.Request( url, data=body, method="POST", headers={ "Authorization": f"Bearer {self.api_key}", "Content-Type": "application/json", "Accept": "application/json", }, ) ``` The command-line interface permits users or calling agents to supply an arbitrary destination: ```python parser.add_argument("--api-key", help=f"ManyChat API key (fallback: ${ENV_API_KEY})") parser.add_argument("--base-url", default=None, help=f"API base URL (default: {DEFAULT_BASE_URL} or ${ENV_BASE_URL})") ``` The environment variable or command-line value is accepted without scheme or hostname validation: ```python def get_client(args: argparse.Namespace) -> ManyChatClient: api_key = args.api_key or os.getenv(ENV_API_KEY) if not api_key: raise CLIError(f"Missing API key. Pass --api-key or set {ENV_API_KEY}.") base_url = args.base_url or os.getenv(ENV_BASE_URL) or DEFAULT_BASE_URL return ManyChatClient(api_key=api_key, base_url=base_url, timeout_seconds=args.timeout) ``` ### Technical Analysis The API host override is not restricted to `https://api.manychat.com`, nor is HTTPS required. Regardless of the selected origin, `ManyChatClient.call()` attaches the production ManyChat credential as an `Authorization: Bearer` header. Consequently, an attacker who can i ...[truncated 2402 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. **Allowlist the production API origin** - Accept `https://api.manychat.com` by default. - Parse the URL with `urllib.parse.urlsplit`. - Reject unexpected schemes, hostnames, ports, user information, query strings, and fragments. 2. **Require HTTPS** - Reject plaintext HTTP destinations to prevent credential interception. - Do not silently normalize or downgrade the scheme. 3. **Restrict development overrides** - Remove `--base-url` and `MANYCHAT_BASE_URL` from normal production operation if they are unnecessary. - If test-server support is required, place it behind an explicit option such as `--allow-untrusted-base-url`. - Display a clear warning and require a separate test credential when that option is used. 4. **Bind credentials to trusted origins** - Attach the authorization header only after confirming that the final request origin is approved. - Prevent credentials from being forwarded if a response redirects to a different origin. - Prefer rejecting redirects for authenticated API requests unless the destination is independently validated. 5. **Validate endpoint paths** - Require relative ManyChat endpoint paths beginning with `/`. - Reject absolute URLs and malformed paths. - Consider allowlisting endpoint prefixes or individual endpoints, especially for agent-driven playbooks and the `raw` command. 6. **Reduce token privileges** - Use a ManyChat credential limited to the operations required by the automation. - Separate read-only lookup credentials from credentials capable of updating subscribers or sending messages where supported. - Rotate the credential immediately if it may have been used with an untrusted base URL. 7. **Add regression tests** - Verify rejection of HTTP URLs, non-ManyChat hosts, embedded credentials, unexpected ports, and cross-origin redirects. - Verify that no authorization header is transmitted before origin validation succeeds. ...[truncated 3 chars]
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
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (9)

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The README explicitly guides agents to look up subscribers, modify tags/fields, and send flows/content, but provides no safety guidance around personal data handling, consent, or outbound messaging controls. In an agent-friendly CLI, that omission is risky because it normalizes automating access to customer records and communications without guardrails, increasing the chance of privacy violations, unauthorized contact, or misuse of production audiences.

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill exposes capabilities that imply environment-variable access, local file reads, and networked API interaction, but it does not declare any explicit tool scope or permissions boundaries. In an agent setting, that omission can cause overbroad execution authority and makes it harder for operators or policy layers to constrain what the skill may access or transmit.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The skill advertises operations like tag changes, custom field updates, subscriber creation, and message/flow sends without warning that these are state-changing actions affecting a live ManyChat account. In agent-driven use, missing warnings increase the chance of unintended mass messaging, subscriber data corruption, or unauthorized business workflow changes.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
This shell script adds a tag, sets a lead score field, and sends a follow-up flow for a subscriber, which are state-changing operations affecting external user data. While the header comment describes the behavior, there is no runtime confirmation, warning, or user-visible disclosure before these actions execute automatically.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
Multiple commands send subscriber identifiers and potentially sensitive personal data such as email, phone number, names, consent status, and custom field values to remote ManyChat API endpoints. While the file is a CLI wrapper, the code provides no confirmation prompt or user-facing disclosure at the point of execution about transmitting this data off-system.

Vague Triggers

Medium
Confidence
84% confidence
Finding
This JSON manifest defines a sequence of actions but provides no information about what user request or context should cause the playbook to run. For manifest files, missing specificity on trigger scope or constraints can lead to unintended invocation because there is no explicit activation boundary or negative examples.

Missing User Warnings

Low
Confidence
84% confidence
Finding
The skill requires a MANYCHAT_API_KEY but provides no guidance on secure handling, storage, or redaction of that credential. In practice, this can lead users or agents to expose secrets in logs, shell history, prompts, or misconfigured environments, enabling account compromise if the key leaks.

Missing User Warnings

Low
Confidence
86% confidence
Finding
The CLI reads the MANYCHAT_API_KEY environment variable to authenticate outbound API requests, but there is no warning or disclosure that the skill accesses credentials from the environment. For agentic use, this can be relevant because the skill explicitly consumes a secret to perform remote actions.

Natural-Language Policy Violations

Low
Confidence
73% confidence
Finding
The tag name "AI Qualified Lead" is a natural-language string fixed in English, with no indication that language selection is user-controlled or that the workflow is intentionally English-only. This can violate language/locale policy when a skill forces a specific language without opt-in or documented justification.

Static analysis

No suspicious patterns detected.