Back to skill

Security audit

mmVoiceMaker

Security checks for vulnerabilities and agentic risk

Overview

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.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/utils.py:13
Finding
Environment-Controlled API Base Can Exfiltrate Credentials and Sensitive User Content<![CDATA[ ## Vulnerability Details **File Location**: `scripts/utils.py:13-15, 160-181`; `scripts/voice_clone.py:80-95, 134-149`; `scripts/sync_tts.py:171-173` **Vulnerability Type**: Unrestricted destination for authenticated sensitive-data requests **Risk Level**: High ### Vulnerable Code ```python # scripts/utils.py:13-15 MINIMAX_VOICE_API_KEY = os.getenv("MINIMAX_VOICE_API_KEY") MINIMAX_API_BASE = os.getenv("MINIMAX_API_BASE", "https://api.minimaxi.com/v1") MINIMAX_API_BASE_BACKUP = "https://api-bj.minimaxi.com/v1" ``` ```python # scripts/utils.py:160-181 base_url = MINIMAX_API_BASE_BACKUP if use_backup else MINIMAX_API_BASE url = f"{base_url}/{endpoint.lstrip('/')}" if files: headers = { "Authorization": f"Bearer {MINIMAX_VOICE_API_KEY}", "Accept-Encoding": "gzip, deflate", } else: headers = get_headers() response = requests.request( method=method, url=url, headers=headers, json=data if not files else None, data=data if files else None, files=files, params=params, timeout=timeout, ) response.raise_for_status() return response.json() ``` ```python # scripts/voice_clone.py:80-95 url = f"{MINIMAX_API_BASE}/files/upload" headers = {"Authorization": f"Bearer {MINIMAX_VOICE_API_KEY}"} with open(file_path, "rb") as f: files = {"file": (os.path.basename(file_path), f)} data = {"purpose": "voice_clone"} response = requests.post( url, headers=headers, files=files, data=data, timeout=timeout, ) ``` ```python # scripts/voice_clone.py:134-149 url = f"{MINIMAX_API_BASE}/files/upload" headers = {"Authorization": f"Bearer {MINIMAX_VOICE_API_KEY}"} with open(file_path, "rb") as f: files = {"file": (os.path.basename(file_path), f)} data = {"purpose": "prompt_audio"} response = requests.post( url, headers=headers, files=files, data=data, timeout=timeout, ) ``` ```python # scripts/sync_tts. ...[truncated 2770 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove arbitrary runtime override support unless it is strictly required. 2. Use a fixed official endpoint for production requests: ```python MINIMAX_API_BASE = "https://api.minimaxi.com/v1" ``` 3. If endpoint customization is necessary, parse and validate it with `urllib.parse.urlsplit`: - Require `https` - Require an explicit allowlisted MiniMax hostname - Reject embedded usernames or passwords - Reject fragments and unexpected ports - Normalize the hostname before comparison 4. Maintain a narrow allowlist, for example: ```python ALLOWED_API_HOSTS = { "api.minimaxi.com", "api-bj.minimaxi.com", } ``` 5. Disable automatic redirects for requests carrying credentials, or verify every redirect target before following it. 6. Do not automatically forward production credentials to custom endpoints. Require a separate credential explicitly configured for a custom endpoint. 7. Before uploading voice samples, clearly disclose the resolved destination and require confirmation when it differs from the official service. 8. Add tests that verify rejection of HTTP URLs, deceptive subdomains, embedded credentials, alternate ports, and attacker-controlled hosts. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/segment_tts.py:671
Finding
Caller-Controlled Temporary Directory Can Trigger Arbitrary Recursive Deletion Under /tmp<![CDATA[ ## Vulnerability Details **File Location**: `scripts/segment_tts.py:671-679` **Vulnerability Type**: Unsafe recursive deletion based on an inadequate path-prefix check **Risk Level**: High ### Vulnerable Code ```python # scripts/segment_tts.py:671-679 if not keep_temp_files and merge_result["success"]: import shutil temp_dir = gen_result["output_dir"] if temp_dir and temp_dir.startswith(tempfile.gettempdir()): try: shutil.rmtree(temp_dir) print(f"Cleaned up temp directory: {temp_dir}") except Exception as e: print(f"Warning: Failed to cleanup temp dir: {e}") ``` ### Technical Analysis `process_segments_to_audio()` accepts a caller-supplied `output_dir`, while `keep_temp_files` defaults to `False`. After successful generation and merging, the function recursively deletes the output directory when its string representation begins with the system temporary-directory path. A string-prefix comparison does not prove that: - The directory was created by this invocation - The directory is dedicated to this Skill - The directory is a child of the intended temporary root - The path does not contain traversal components - The path is not the temporary root itself - The path is not a symlink or otherwise resolves to an unexpected location For a typical temporary root of `/tmp`, values such as `/tmp`, `/tmp-important`, or a crafted path containing traversal components satisfy `startswith("/tmp")`. The code then passes the value directly to `shutil.rmtree()`. Although the CLI currently forces `keep_temp_files=True`, the vulnerable function is exported through the `scripts` package and can be called directly by integrations, examples, or other Agent code. Therefore, the unsafe deletion path remains reachable. ### Attack Path 1. An application or Agent invokes the exported function directly with a caller-selected output directory: ```python process_segments_to_audio( segments_file ...[truncated 1325 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Track whether the directory was created internally by the current invocation: ```python created_temp_dir = output_dir is None if created_temp_dir: output_dir = tempfile.mkdtemp(prefix="mmvoice_segments_") ``` 2. Only recursively remove a directory when `created_temp_dir` is true. 3. Never recursively delete a caller-supplied output directory. For caller-supplied directories, remove only the exact segment files created during the current run. 4. Resolve and validate paths before cleanup: ```python temp_root = Path(tempfile.gettempdir()).resolve() candidate = Path(temp_dir).resolve(strict=True) ``` 5. Explicitly reject deletion when the candidate equals the temporary root. 6. Require the resolved candidate to be a strict child of the temporary root and to have the expected `mmvoice_segments_` naming prefix. 7. Record generated files in an internal list and delete only those paths after verifying that each resolved path remains inside the owned directory. 8. Avoid following symlinks during cleanup and check for path replacement races where the threat model includes concurrent local attackers. 9. Add regression tests for `/tmp`, prefix-confusion paths such as `/tmp-important`, traversal paths, symlinks, and caller-owned directories. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
Findings (68)

Tainted flow: 'headers' from os.getenv (line 210, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Content
# 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")
Confidence
96% confidence
Finding
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.

Tainted flow: 'url' from os.getenv (line 161, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Content
Returns:
        Saved file path
    """
    response = requests.get(url, timeout=timeout)
    response.raise_for_status()
    
    with open(output_path, "wb") as f:
Confidence
94% confidence
Finding
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.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
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.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
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.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
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.

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding
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.

Natural-Language Policy Violations

High
Confidence
97% confidence
Finding
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.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
- 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
Confidence
90% confidence
Finding
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.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
**After generation:**
- Verify output audio quality
- If satisfied, delete intermediate files: `rm -rf ./audio/tmp/`

**Behavior by Model:**
Confidence
85% confidence
Finding
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).

Intent-Code Divergence

High
Confidence
98% confidence
Finding
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.

Lp3

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding
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.

Natural-Language Policy Violations

Medium
Confidence
83% confidence
Finding
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 call

Medium
Category
Dangerous Code Execution
Content
def check_ffmpeg() -> Tuple[bool, Optional[str]]:
    """Check if FFmpeg is installed"""
    try:
        result = subprocess.run(
            ["ffmpeg", "-version"],
            capture_output=True,
            text=True,
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
print_success(f"FFmpeg is installed: {version_line}")
            
            # Get path
            path_result = subprocess.run(
                ["which", "ffmpeg"],
                capture_output=True,
                text=True
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Session Persistence

Medium
Category
Rogue Agent
Content
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
Confidence
90% confidence
Finding
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.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
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.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
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.

Context-Inappropriate Capability

Medium
Confidence
88% confidence
Finding
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 call

Medium
Category
Dangerous Code Execution
Content
return 1
    
    # Run check script
    result = subprocess.run([sys.executable, str(check_script)] + sys.argv[2:])
    return result.returncode
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
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.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
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.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
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.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
brew install ffmpeg

# Ubuntu/Debian:
sudo apt install ffmpeg

# Windows: Download from https://ffmpeg.org/download.html
```
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
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.

Natural-Language Policy Violations

Medium
Confidence
90% confidence
Finding
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.

Static analysis

No suspicious patterns detected.