T09 · Insecure Skill Coding Practices
- Location
scripts/stream_play.py:158- Finding
WebSocket TLS Certificate and Hostname Verification Disabled
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This MiniMax text-to-speech skill is coherent in purpose, but it handles API credentials unsafely and weakens secure network protections.
Review before installing. Do not paste a real MiniMax API key into SKILL.md or the Python files; use an environment variable or secret store instead. Avoid streaming mode until TLS verification is fixed, and do not use custom base URLs unless you fully trust the endpoint. Treat any text sent to this skill as being transmitted to a third-party TTS service.
scripts/stream_play.py:158WebSocket TLS Certificate and Hostname Verification Disabled
scripts/generate.py:135API Credentials and User Text Can Be Sent to an Arbitrary Endpoint
SKILL.md:61Initialization Instructions Require API Keys to Be Stored in Plaintext Source Files
SKILL.md:81Voice Selection Workflow Requests Unnecessary Access to Agent Identity Data
scripts/requirements.txt:1Runtime Dependencies Are Installed Without Reproducible Version or Integrity Controls
These initialization steps tell the operator to place the real API key into two scripts and a visible configuration section, with no warning against plaintext secret storage. This materially increases the risk of secret leakage and unauthorized API use because the credential is replicated across multiple human-readable locations.
The code explicitly disables TLS certificate verification by setting check_hostname=False and verify_mode=ssl.CERT_NONE for the WebSocket connection. This allows machine-in-the-middle interception or modification of the TTS stream and API traffic, including exposure of the bearer token and tampering with returned audio data.
The description advertises external API use, WebSocket streaming, and file output, but does not clearly warn users that submitted text will be transmitted to a third-party service and may be saved locally. In a TTS context, this can expose sensitive user content or create privacy surprises, especially when streaming is preferred by default.
The trigger guidance is extremely broad and says this skill should be preferred for essentially any TTS-related phrasing. While not a direct code-execution flaw, overly broad activation can cause the agent to invoke a networked, file-writing skill in situations where the user did not clearly consent to external processing or persistent output.
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
- **websockets 库**:`pip3 install websockets`(流式播放需要)
- **ffplay**(流式播放需要):
- macOS: `brew install ffmpeg`
- Ubuntu: `sudo apt install ffmpeg`
- Windows: 从 https://ffmpeg.org/download.html 下载
- 如果 ffplay 未安装,`stream_play.py` 会提示安装方法
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
- **websockets 库**:`pip3 install websockets`(流式播放需要)
- **ffplay**(流式播放需要):
- macOS: `brew install ffmpeg`
- Ubuntu: `sudo apt install ffmpeg`
- Windows: 从 https://ffmpeg.org/download.html 下载
- 如果 ffplay 未安装,`stream_play.py` 会提示安装方法
The initialization workflow directs the agent/operator to collect the user's API key and persist it in multiple files, including scripts and documentation. Persisting secrets in plaintext across the workspace broadens the attack surface and makes later disclosure through shared directories, backups, or repository sync more likely.
The skill explicitly instructs the operator to hardcode the MiniMax API key and base URL into multiple scripts, despite the manifest already declaring environment-based secret handling. Embedding credentials in source files increases the chance of accidental disclosure through version control, logs, backups, screenshots, or later reuse by other users of the workspace.
The configuration table explicitly instructs replacing a placeholder with the actual API key, encouraging plaintext retention in the markdown file itself. A markdown file is especially easy to inspect, copy, sync, or commit accidentally, making credential compromise more likely.
The script transmits arbitrary user-supplied text to a third-party TTS service, but it provides no explicit consent prompt, privacy notice, or redaction safeguards before sending potentially sensitive content off-host. In a skill context, users may assume local processing, so secrets, personal data, or confidential prompts could be exposed to the remote provider unintentionally.
The code performs an outbound HTTP request containing the full input text and an authorization token, which creates a real data exfiltration path to an external service. This is expected for a cloud TTS wrapper, but it remains security-relevant because users may pass confidential content and the '--base-url' override can redirect data to an unintended endpoint.
# 发送请求
try:
resp = requests.post(
f"{base_url}/v1/t2a_v2",
headers={
"Authorization": f"Bearer {api_key}",
User-facing usage text, help descriptions, and operational messages are presented in Chinese only, and the example input text is also Chinese. There is no indication that the tool is region-specific or that users can opt into another language, which conflicts with the policy against forcing a specific language without user choice.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
def start_ffplay():
"""启动 ffplay 子进程,从 stdin 读取音频数据播放"""
try:
process = subprocess.Popen(
[
"ffplay",
"-nodisp", # 不显示窗口
This markdown file contains user-facing natural-language content in Chinese for multiple changelog entries, but there is no indication that the skill is intentionally region-specific or that users can choose another language. Under the policy, forcing a specific language without opt-in can be a natural-language policy violation.
Substantial setup and usage guidance is written only in Chinese, which effectively imposes a language requirement on operators without stating that the skill is Chinese-only or offering an alternative language. Under the policy, forced language/locale constraints should be either optional or clearly documented and justified.
The dependency is specified with a minimum version bound only, which makes builds non-reproducible and allows different environments to install different upstream releases. This can unintentionally introduce vulnerable or breaking versions through supply-chain drift, even if no specific exploit is present in the manifest itself.
requests>=2.28.0
websockets>=12.0
The manifest references requests without an exact version while the package has multiple known advisories across its release history. Because the installed version is not fixed, it is impossible to verify from this file alone whether deployments will receive a safe version, creating avoidable supply-chain uncertainty.
The websockets package is unpinned, so installations may resolve to different versions over time depending on when and where the skill is deployed. That weakens reproducibility and can expose the project to newly introduced vulnerable or incompatible releases without any code change in the repository.
requests>=2.28.0
websockets>=12.0
The websockets dependency has known historical advisories, but this manifest does not constrain the installed version to a reviewed safe release. That means consumers of the skill could install an affected version unknowingly, especially in fresh or automated environments.