Back to skill

Security audit

CMI CPaaS - SMS Sender

Security checks for vulnerabilities and agentic risk

Overview

The skill does what it claims, but it handles SMS credentials and billable message sending in a way users should review before installing.

Review before installing if you will use real CloudSMS credentials. Prefer a version that reads the Auth Key from a protected secret source, asks for confirmation before sending, enforces recipient and message limits locally, and does not silently clear proxy settings.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/send_bulk_sms.py:95
Finding
CloudSMS Authentication Key Exposed Through Command-Line Arguments<![CDATA[ ## Vulnerability Details **File Location**: `scripts/send_bulk_sms.py:95-99` and `SKILL.md:86-90` **Vulnerability Type**: Sensitive credential exposure through process arguments **Risk Level**: High ### Vulnerable Code ```python channel = sys.argv[1] auth_key = sys.argv[2] mobile = sys.argv[3] content = sys.argv[4] signature = sys.argv[5] if len(sys.argv) > 5 else None ``` The documented invocation explicitly places the authentication key on the command line: ```bash python3 scripts/send_bulk_sms.py "<channel_id>" "<auth_key>" "<mobile>" "<content>" ["<signature>"] ``` ### Technical Analysis The CloudSMS authentication key is accepted as `sys.argv[2]`. Command-line arguments are not an appropriate secret-transport mechanism because they may be exposed through: - Process inspection utilities and operating-system process metadata. - Agent execution logs and tool-call traces. - Shell command history. - Job schedulers, monitoring platforms, and audit telemetry. - Error reports that capture complete command invocations. The Channel ID and authentication key together authorize requests to the external SMS service. Although the script does not print the key directly, passing it through the process command line expands its exposure beyond the intended script. ### Attack Path 1. A user supplies a valid CloudSMS Channel ID and authentication key to the Skill. 2. The agent invokes the script with both credentials embedded in the command line. 3. A local user, monitoring service, command logger, or other process with access to process metadata or execution logs records the invocation. 4. The observer extracts the Channel ID and authentication key. 5. The exposed credentials are used to submit independent requests to the CloudSMS API. 6. The attacker can send messages and consume resources within the permissions and balance of the compromised CloudSMS account. ### Impact Assessment This issue does not grant additional operating-system privileges by its ...[truncated 365 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Do not pass the authentication key through command-line arguments. - Retrieve the key from a dedicated secret manager where available. - As a fallback, read the key from a protected environment variable or standard input. Standard input should be used in a way that does not echo or log the value. - Pass only a secret reference or identifier through the command line, not the secret itself. - Ensure agent tool-call traces, subprocess logs, exception handlers, and telemetry redact the Channel ID and authentication key. - Restrict the secret's file or environment access to the executing account. - Rotate any authentication keys that may already have appeared in command histories or execution logs. - Update `SKILL.md` so its invocation example no longer instructs the agent to include the key in the command line. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/send_bulk_sms.py:98
Finding
Documented Recipient and Message Limits Are Not Enforced<![CDATA[ ## Vulnerability Details **File Location**: `scripts/send_bulk_sms.py:98-103` **Vulnerability Type**: Missing input validation and resource-consumption controls **Risk Level**: Medium ### Vulnerable Code ```python mobile = sys.argv[3] content = sys.argv[4] signature = sys.argv[5] if len(sys.argv) > 5 else None # 处理手机号列表 mobile_list = [m.strip() for m in mobile.split(',')] result = send_sms(channel, auth_key, mobile_list, content, signature) ``` The documentation declares that recipients must include a country code, each request may contain no more than 100 recipients, and message content may contain no more than 500 characters. The implementation does not enforce any of these restrictions before submitting the request. ### Technical Analysis The script splits the supplied recipient string and immediately passes the resulting list to `send_sms`. It does not validate: - Whether the recipient list is empty. - Whether empty entries are present. - Whether recipients use a valid international telephone-number format. - Whether the number of recipients exceeds 100. - Whether the message content is empty or exceeds 500 characters. - Whether the signature causes the effective message length to exceed the documented limit. Documentation is not an effective security control. Inputs may originate from natural-language extraction, direct script execution, or another automated caller and therefore must be validated in the executable code. The remote CloudSMS API may independently reject some invalid requests, but the project cannot rely on undocumented server-side behavior for enforcement. If the remote service accepts a larger recipient list, a single invocation could cause more extensive and costly message delivery than the Skill claims to permit. ### Attack Path 1. An attacker or untrusted user obtains the ability to request SMS delivery through the Skill using valid account credentials. 2. The attacker supplies more than 100 comma-separated recipien ...[truncated 878 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Validate all inputs locally before constructing or transmitting the API request: - Reject an empty recipient string and empty recipient entries. - Enforce a maximum of 100 recipients after splitting and normalization. - Validate each recipient using an appropriate international telephone-number parser or a strict E.164-compatible policy. - Reject empty message content. - Enforce the documented 500-character limit, accounting for the signature if the platform includes it in the limit. - Set explicit reasonable byte-size limits as well as character limits. - Reject control characters or unsupported content where required by the provider. - Return a structured validation error without contacting the remote API. - Apply account-level quotas, rate limits, and confirmation controls for unusually large or costly sends. - Add automated tests for empty values, malformed numbers, 100 and 101 recipients, oversized content, and signature-adjusted content length. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
scripts/send_bulk_sms.py:87
Finding
Incorrect Argument-Count Check Allows an Unhandled IndexError<![CDATA[ ## Vulnerability Details **File Location**: `scripts/send_bulk_sms.py:87-99` **Vulnerability Type**: Improper input validation leading to process termination **Risk Level**: Low ### Vulnerable Code ```python def main(): if len(sys.argv) < 4: print(json.dumps({ "success": False, "error": "参数不足。用法: send_bulk_sms.py <channel> <auth_key> <mobile> <content> [signature]" }, ensure_ascii=False, indent=2)) sys.exit(1) channel = sys.argv[1] auth_key = sys.argv[2] mobile = sys.argv[3] content = sys.argv[4] signature = sys.argv[5] if len(sys.argv) > 5 else None ``` ### Technical Analysis The script requires four mandatory user-supplied arguments: `channel`, `auth_key`, `mobile`, and `content`. Including the program name, `sys.argv` must therefore contain at least five elements. The validation only rejects invocations where `len(sys.argv) < 4`. An invocation containing exactly four elements passes the check, but `content = sys.argv[4]` then accesses a nonexistent element and raises an unhandled `IndexError`. This produces an uncontrolled traceback rather than the script's documented structured JSON error. In an automated agent workflow, malformed input can consequently interrupt execution and make downstream result parsing fail. ### Attack Path 1. A caller invokes the script with only three supplied arguments, such as the Channel ID, authentication key, and recipient. 2. `len(sys.argv)` is four because the program name is included. 3. The condition `len(sys.argv) < 4` evaluates to false. 4. Execution reaches `content = sys.argv[4]`. 5. Python raises an unhandled `IndexError`, terminating the process and bypassing the intended JSON error response. ### Impact Assessment The issue provides no privilege escalation and does not grant access to CloudSMS resources. Its direct impact is limited to availability and reliability: a malformed invocation can crash the current process, disrupt t ...[truncated 205 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Change the minimum argument check to require at least five `sys.argv` elements: ```python if len(sys.argv) < 5: # Return the structured usage error. ``` - Prefer `argparse` or another structured command-line parser to define mandatory and optional parameters. - Catch parsing and validation failures at the program boundary and return consistent structured JSON without a traceback. - Add tests covering zero arguments, every partially supplied argument set, the exact minimum valid invocation, and optional signature handling. - Avoid including credentials in usage examples or exception output while correcting the argument parser. ]]>
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 (7)

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The skill instructs the agent to collect Channel ID, Auth Key, recipient phone numbers, and message content, then send them to an external CloudSMS API, but it does not clearly warn users that this data leaves the system and is disclosed to a third party. This creates a privacy and consent risk because users may provide sensitive personal data or confidential message content without understanding the external transmission.

External Transmission

Medium
Category
Data Exfiltration
Content
payload["uip_body"]["ORIGINAL_ADDR"] = original_addr

    try:
        response = requests.post(API_URL, json=payload, timeout=30)
        result = response.json()

        uip_head = result.get("uip_head", {})
Confidence
80% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
This code performs an HTTP POST containing SMS content and destination phone numbers, which is a privacy- and cost-impacting action. Aside from internal comments/docstrings, there is no user-facing confirmation prompt or warning before the transmission occurs.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The auth_key is taken from command-line arguments and transmitted in the request payload, but the script does not warn users that they are supplying sensitive credentials or that command-line arguments may be exposed in shell history and process listings. This is a safety-relevant credential-handling operation lacking user disclosure.

Natural-Language Policy Violations

Low
Confidence
88% confidence
Finding
The entire skill description and invocation examples are presented only in Chinese, which can amount to a language/locale constraint in natural-language instructions. There is no indication that users may choose another language or that the skill is intentionally limited to a Chinese-language or region-specific audience.

Natural-Language Policy Violations

Low
Confidence
86% confidence
Finding
The top-level description and user-facing usage/error strings are written only in Chinese, which can amount to a forced language choice if this skill is intended for a broader audience. There is no opt-in, alternative locale, or documented justification that the skill is China-specific only.

Intent-Code Divergence

Low
Confidence
97% confidence
Finding
The error message documents the command as requiring `<channel> <auth_key> <mobile> <content> [signature]`, which means `content` is mandatory. However, the guard checks `len(sys.argv) < 4` and the code then unconditionally accesses `sys.argv[4]`, so invocations missing `content` bypass the documented validation and fail differently than the stated interface implies.

Static analysis

No suspicious patterns detected.