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

Content
View full analysis
5 else None ``` The documented invocation explicitly places the authentication key on the command line: ```bash python3 scripts/send_bulk_sms.py "" "" "" "" [""] ``` ### 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
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/send_bulk_sms.py:98
Finding

Documented Recipient and Message Limits Are Not Enforced

Content
View full analysis
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
View remediation

T09 · Insecure Skill Coding Practices

Note
Location
scripts/send_bulk_sms.py:87
Finding

Incorrect Argument-Count Check Allows an Unhandled IndexError

Content
View full analysis
[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
View remediation
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
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/send_bulk_sms.py (reported line 53)May include surrounding context.

python
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", {})

Missing User Warnings

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.