T09 · Insecure Skill Coding Practices
- Location
scripts/tts_sync.py:147- Finding
API Key Exposure Through Command-Line Arguments
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This MiniMax TTS skill is mostly coherent, but it deserves review because it can clone and delete account voices while sending text, voice metadata, and API credentials to a third-party service with limited safeguards.
Install only if you are comfortable sending synthesis text, task metadata, voice IDs, and voice-cloning inputs to MiniMax. Use MINIMAX_API_KEY instead of --api-key, avoid sensitive or unauthorized voice samples, and manually confirm voice IDs before using deletion because deleted custom voices are documented as unrecoverable.
scripts/tts_sync.py:147API Key Exposure Through Command-Line Arguments
scripts/tts_sync.py:87Unvalidated Server-Provided URL Used for Audio Download
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
}
print(f"正在创建异步任务...")
response = requests.post(url, json=payload, headers=headers, timeout=30)
result = response.json()
if result.get("base_resp", {}).get("status_code") != 0:
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
headers = {"Authorization": f"Bearer {api_key}"}
response = requests.get(url, headers=headers, timeout=30)
return response.json()
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
}
print(f"正在创建语音合成任务...")
response = requests.post(url, json=payload, headers=headers, timeout=30)
result = response.json()
if result.get("base_resp", {}).get("status_code") != 0:
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
url = f"https://api.minimaxi.com/v1/query/t2a_async_query_v2?task_id={task_id}"
headers = {"Authorization": f"Bearer {api_key}"}
response = requests.get(url, headers=headers, timeout=30)
return response.json()
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
"""下载音频到本地"""
api_key = api_key or os.getenv("MINIMAX_API_KEY")
file_resp = requests.get(
f"https://api.minimaxi.com/v1/files/retrieve?file_id={file_id}",
headers={"Authorization": f"Bearer {api_key}"}
)
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
}
print(f"正在复刻音色...")
response = requests.post(url, json=payload, headers=headers, timeout=60)
result = response.json()
if result.get("base_resp", {}).get("status_code") != 0:
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
}
print(f"正在查询音色列表 ({voice_type})...")
response = requests.post(url, json=payload, headers=headers, timeout=30)
result = response.json()
if result.get("base_resp", {}).get("status_code") != 0:
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
}
print(f"正在查询音色列表 ({voice_type})...")
response = requests.post(url, json=payload, headers=headers, timeout=30)
result = response.json()
if result.get("base_resp", {}).get("status_code") != 0:
The skill includes destructive voice-management capability (/v1/del_voice) while presenting itself primarily as a TTS skill, without clearly surfacing deletion risk or operational guardrails. Hidden or underemphasized destructive behavior can mislead users and agents into invoking actions beyond expected text-to-speech functionality.
The skill includes destructive voice-management capability (/v1/del_voice) while presenting itself primarily as a TTS skill, without clearly surfacing deletion risk or operational guardrails. Hidden or underemphasized destructive behavior can mislead users and agents into invoking actions beyond expected text-to-speech functionality.
The document describes uploading source audio for voice cloning and obtaining a reusable cloned voice without any warning about consent, privacy, or the handling of biometric voice data. Because voiceprints are sensitive personal data and cloning can enable impersonation and fraud, omitting consent and disclosure safeguards is a real security/privacy issue in this skill context.
The skill documents use of environment variables and outbound network access to a third-party API, but it declares no explicit tool scope or permissions. In an agent environment, this weakens least-privilege controls and can cause users or orchestrators to underestimate the skill's ability to read secrets and transmit data externally.
The skill sends user-provided text and related metadata to an external service but does not clearly disclose that network transmission or associated privacy implications. In an agent setting, undisclosed third-party transmission can expose sensitive prompts, personal data, or confidential content to external processors.
The skill sends user-provided text and related metadata to an external service but does not clearly disclose that network transmission or associated privacy implications. In an agent setting, undisclosed third-party transmission can expose sensitive prompts, personal data, or confidential content to external processors.
This code transmits user content and an authorization bearer token to an external API. External transmission is expected for a cloud TTS skill, but it remains security-relevant because sensitive text may leave the local environment and because misuse of the API key could expose the account to unauthorized usage.
API_KEY = os.getenv("MINIMAX_API_KEY")
# 1. 创建任务
response = requests.post(
"https://api.minimaxi.com/v1/t2a_async_v2",
headers={
"Authorization": f"Bearer {API_KEY}",
This code transmits user content and an authorization bearer token to an external API. External transmission is expected for a cloud TTS skill, but it remains security-relevant because sensitive text may leave the local environment and because misuse of the API key could expose the account to unauthorized usage.
API_KEY = os.getenv("MINIMAX_API_KEY")
# 1. 创建任务
response = requests.post(
"https://api.minimaxi.com/v1/t2a_async_v2",
headers={
"Authorization": f"Bearer {API_KEY}",
The status polling request sends task identifiers and authorization data to the external MiniMax API. This is expected operational behavior for async TTS, but it still constitutes externally visible metadata flow and should be disclosed and permission-scoped in agent environments.
# 2. 查询状态
status_resp = requests.get(
f"https://api.minimaxi.com/v1/query/t2a_async_query_v2?task_id={task_id}",
headers={"Authorization": f"Bearer {API_KEY}"}
)
status = status_resp.json()["status"] # Processing / Success / Failed
The file retrieval step obtains a downloadable audio URL from the external service and then fetches content from that URL for local storage. Following a remotely supplied download URL increases risk compared with fixed-host API calls because it can broaden network exposure and may fetch untrusted content if host validation is absent.
if status == "Success":
file_id = status_resp.json()["file_id"]
file_resp = requests.get(
f"https://api.minimaxi.com/v1/files/retrieve?file_id={file_id}",
headers={"Authorization": f"Bearer {API_KEY}"}
)
download_url = file_resp.json()["file"]["download_url"]
The reference explicitly documents a remote API endpoint for creating TTS tasks. In a TTS integration this is expected behavior, but it still represents a genuine external data transfer path that can expose confidential text if users are not warned or if the integration is used with sensitive material.
## 基础信息
- **创建任务**: `POST https://api.minimaxi.com/v1/t2a_async_v2`
- **查询状态**: `GET https://api.minimaxi.com/v1/query/t2a_async_query_v2`
- **认证**: Bearer Token
- **适用场景**: 长文本(最长 5 万字符)
The document instructs users to send arbitrary text to an external TTS provider but does not warn that submitted content is transmitted off-platform and may be stored or processed by a third party. In this skill’s context, users may submit long text, sensitive documents, or voice-cloning material, so the omission creates a real privacy and data-handling risk.
The status-query endpoint also sends task identifiers and credentials to the external provider. This is lower impact than text submission, but task metadata and file identifiers can still reveal usage patterns or enable access to generated artifacts if mishandled.
## 基础信息
- **创建任务**: `POST https://api.minimaxi.com/v1/t2a_async_v2`
- **查询状态**: `GET https://api.minimaxi.com/v1/query/t2a_async_query_v2`
- **认证**: Bearer Token
- **适用场景**: 长文本(最长 5 万字符)
This finding duplicates the same external POST transmission in the example code. The risk is not the mere presence of HTTPS requests, but that the example normalizes sending potentially sensitive content to a third-party service without any warnings about privacy, retention, or compliance obligations.
API_KEY = os.getenv("MINIMAX_API_KEY")
response = requests.post(
"https://api.minimaxi.com/v1/t2a_async_v2",
headers={
"Authorization": f"Bearer {API_KEY}",
This finding duplicates the same external POST transmission in the example code. The risk is not the mere presence of HTTPS requests, but that the example normalizes sending potentially sensitive content to a third-party service without any warnings about privacy, retention, or compliance obligations.
API_KEY = os.getenv("MINIMAX_API_KEY")
response = requests.post(
"https://api.minimaxi.com/v1/t2a_async_v2",
headers={
"Authorization": f"Bearer {API_KEY}",
The example embeds the external MiniMax endpoint in executable sample code, making third-party transmission easy to adopt without security review. In this skill context, that increases the chance that developers will forward full user text or sensitive material directly to the provider by default.
API_KEY = os.getenv("MINIMAX_API_KEY")
response = requests.post(
"https://api.minimaxi.com/v1/t2a_async_v2",
headers={
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json"
The GET polling example transmits task status queries to the provider and includes the bearer token in headers. Although normal for async APIs, documenting this without caution can lead to accidental exposure of API credentials or over-logging of task identifiers and generated file references.
response = requests.get(
f"https://api.minimaxi.com/v1/query/t2a_async_query_v2?task_id={task_id}",
headers={"Authorization": f"Bearer {API_KEY}"}
)