T09 · Insecure Skill Coding Practices
- Location
scripts/utils.py:13- Finding
Environment-Controlled API Base Can Exfiltrate Credentials and Sensitive User Content
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This voice-generation skill is mostly purpose-aligned, but it handles API keys, private text, and voice recordings with under-scoped network and deletion behavior that deserves review before installation.
Review before installing. Use it only with a MiniMax API key you are comfortable sending to MiniMax, do not set MINIMAX_API_BASE to an untrusted host, and only upload voice samples you own or have explicit permission to use. Avoid dry_run=False cleanup helpers unless you have reviewed the exact voices to delete, and prefer manual deletion of known temp files over broad recursive cleanup commands.
scripts/utils.py:13Environment-Controlled API Base Can Exfiltrate Credentials and Sensitive User Content
scripts/segment_tts.py:671Caller-Controlled Temporary Directory Can Trigger Arbitrary Recursive Deletion Under /tmp
The script reads MINIMAX_VOICE_API_KEY from the environment and transmits it in an Authorization header to an external service during the optional API test. Even though this is expected for API authentication, it is still credential transmission off-host and can surprise users if they invoke --test-api without a clear inline consent prompt or destination warning.
# Try to list system voices (lightweight operation)
url = "https://api.minimaxi.com/v1/text_to_speech/voice_list"
response = requests.get(url, headers=headers, timeout=10)
if response.status_code == 200:
print_success("API connectivity test passed")
The function downloads arbitrary content from a caller-supplied URL with no allowlist, scheme validation, or destination controls. In an agent skill, this can enable SSRF against internal services or unauthorized fetching of attacker-controlled content, which is then written to disk for later processing.
Returns:
Saved file path
"""
response = requests.get(url, timeout=timeout)
response.raise_for_status()
with open(output_path, "wb") as f:
The code is narrowly focused on async TTS for long text. It creates/querys MiniMax async speech synthesis tasks, uploads text input files, waits for completion, and downloads resulting audio. While this matches part of the declared description ('voice synthesis'), the description materially overstates the implemented capabilities by asserting support for voice cloning, voice design, and FFmpeg-based audio post-processing/merging, none of which appear in the supplied code. This is a description-to-behavior mismatch because several advertised core capabilities are absent from the actual implementation shown.
The code chunk’s actual behavior is narrowly focused on text-to-speech synthesis and streaming audio retrieval from the MiniMax API. It constructs TTS requests, handles WebSocket task flow, converts returned hex audio to bytes, and can save output audio locally. However, the declared description claims broader capabilities—voice cloning, voice design, and audio post-processing/merging using FFmpeg—that are not present in this code. This is a description-behavior mismatch because substantial advertised capabilities are unsupported by the supplied implementation chunk.
The supplied code is narrowly focused on voice cloning workflows: uploading clone/prompt audio, invoking the MiniMax voice clone API, and optionally saving preview audio. That behavior is consistent with part of the description ('voice cloning' and creating custom voices), but the declaration is broader and asserts additional capabilities—voice synthesis, voice design, and audio post-processing/merging using FFmpeg—that are not present in this code chunk. There is no evidence here of FFmpeg invocation, audio merging, or general TTS generation from arbitrary text apart from an optional clone preview generated by the cloning API. Therefore the description does not accurately represent what this specific code chunk actually does.
The code chunk is a voice-management module, not a synthesis or audio-processing module. Its concrete actions are retrieving voice lists from the API, printing/querying metadata, checking whether a voice exists, and deleting cloned/designed voices, including a bulk cleanup function. The declared description is substantially broader and materially different: it says the skill enables voice synthesis, voice cloning, voice design, and FFmpeg-based audio processing. None of those creation/processing capabilities appear in this code. Additionally, the code includes deletion/cleanup behavior, which is a significant capability not reflected in the description. Therefore the description does not accurately represent this code chunk.
The instructions say agents 'MUST always match gender first' and call it 'non-negotiable,' requiring male characters to use male voices and female characters to use female voices. This is a natural-language policy issue because it forces a sensitive attribute-based presentation choice rather than offering the user a choice or allowing contextual exceptions.
The documentation recommends using a destructive shell command, 'rm -rf ./audio/tmp/', to delete intermediate files. In an agent context, this is dangerous because path assumptions may be wrong, the working directory may be unexpected, or a user/agent could adapt the pattern unsafely, leading to unintended file deletion.
- Output: `./audio/output.mp3` (if `-o` not specified)
- Intermediate files: `./audio/tmp/` (if `--temp-dir` not specified)
- Finally, ask user to confirm whether to delete intermediate files: `rm -rf ./audio/tmp/`
### Validate Segments File
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
**After generation:**
- Verify output audio quality
- If satisfied, delete intermediate files: `rm -rf ./audio/tmp/`
**Behavior by Model:**
The function name and docstring state it cleans up 'unused' voices, but the implementation unconditionally deletes every cloned and designed voice returned by the API. This mismatch is dangerous because callers may invoke it believing it performs safe garbage collection, when it actually causes irreversible broad data loss.
The skill instructs the agent to use shell commands, read/write files, access environment variables, and make network/API calls, but it does not declare any explicit tool scope such as allowed-tools or permissions. This creates an authorization gap where the runtime may grant broader capabilities than users expect, increasing the chance of unintended command execution, filesystem modification, or secret handling.
The file states that the voice 'MUST match the content language' and to 'Never assign a voice from the wrong language.' This rigid language constraint can violate organizational language/locale policy expectations because it removes user choice and forces a specific locale behavior without opt-in or documented justification.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
def check_ffmpeg() -> Tuple[bool, Optional[str]]:
"""Check if FFmpeg is installed"""
try:
result = subprocess.run(
["ffmpeg", "-version"],
capture_output=True,
text=True,
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
print_success(f"FFmpeg is installed: {version_line}")
# Get path
path_result = subprocess.run(
["which", "ffmpeg"],
capture_output=True,
text=True
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
print_error("MINIMAX_VOICE_API_KEY is NOT set")
print_info("Set it with:")
print_info(' export MINIMAX_VOICE_API_KEY="your-api-key-here"')
print_info("Or add to ~/.bashrc or ~/.zshrc for persistence")
return False, None
The API connectivity test sends the user's bearer credential to MiniMax as part of a live network request, but the call site does not present a specific warning immediately before transmission. In a security review context, hidden or insufficiently signposted credential use is risky because environment-check scripts are often assumed to be local-only diagnostics.
The clone command accepts a user-supplied audio file and sends it to a voice-cloning backend without any explicit consent, ownership, or privacy warning. In a voice-cloning context, that is materially risky because users may upload third-party biometric voice data or sensitive recordings without understanding that the content leaves the local system.
The manifest describes voice synthesis, cloning, design, and audio post-processing, but this command executes a separate Python script via subprocess. Launching an auxiliary process is not an obvious requirement of the skill's user-facing purpose and expands capability beyond direct voice/audio operations.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
return 1
# Run check script
result = subprocess.run([sys.executable, str(check_script)] + sys.argv[2:])
return result.returncode
This markdown file documents uploading source audio and prompt audio for voice cloning, which transmits potentially sensitive biometric voice data to a remote service. The section lists technical file requirements but provides no warning about consent, privacy, or that audio leaves the local system.
The markdown describes deleting cloned/designed voices and running cleanup with dry_run=False, which can permanently remove custom voices. Although a dry-run example is shown, there is no explicit warning that these actions are destructive or irreversible.
The guide documents voice cloning but provides no warning about consent, impersonation risk, or the handling of uploaded biometric voice data. In a voice-synthesis skill, this omission is security- and safety-relevant because it can normalize unauthorized cloning of a person's voice and lead to privacy, fraud, or social-engineering abuse.
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
brew install ffmpeg
sudo apt install ffmpeg
The examples show destructive voice-deletion operations, including a batch cleanup that can delete all custom voices, without any explicit warning, confirmation step, or safety guidance. In a copy-paste examples file, this increases the chance that users will run irreversible commands and unintentionally delete cloned or designed voices they still need.
The guidance explicitly instructs voice selection based on character gender, which can cause the agent to infer or enforce gendered attributes without user opt-in. In a voice-cloning and synthesis skill, this can lead to misgendering, biased assignments, and privacy-sensitive inference about people described in text, especially when processing real-world individuals or ambiguous characters.
No suspicious patterns detected.