Back to skill

Security audit

MiniMax TTS Generator

Security checks for vulnerabilities and agentic risk

Overview

This TTS skill mostly does what it claims, but it can send the user's text and MiniMax API key to an arbitrary environment-selected API host without validation.

Review before installing. Use only in a trusted environment, do not set MINIMAX_API_HOST unless you fully trust the endpoint, and assume any text you submit is sent to MiniMax or to whatever host that variable names. Prefer a dedicated, low-quota MiniMax API key and rotate it if the skill was ever run with an unexpected host override.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/minimax_tts.py:73
Finding

Arbitrary API Host Override Exposes API Credentials and Submitted Text

Content
View full analysis
bytes: """Make request to MiniMax TTS speech-2.6 API (OpenAI-compatible). Returns binary audio.""" key = get_api_key() if not key: raise Exception( 'MINIMAX_API_KEY not set. ' 'Set via environment or openclaw config: ' 'openclaw config set skills.entries.minimax-tts.apiKey "sk-your-key"' ) host = get_api_host() url = f'{host}{ENDPOINT_SIMPLE}' headers = { 'Authorization': f'Bearer {key}' } response = requests.post(url, json=data, headers=headers, timeout=120) response.raise_for_status() # speech-2.6 returns binary audio directly if response.headers.get('Content-Type', '').startswith('audio/'): return response.content # If JSON, check for error resp_json = response.json() base_resp = resp_json.get('base_resp', {}) status_code = base_resp.get('status_code', 0) if status_code != 0: raise Exception(f"API error {status_code}: {base_resp.get('status_msg', 'Unknown error')}") raise Exception('Unexpected response format from speech-2.6 API') def make_request_native(data: dict) -> dict: """Make request to MiniMax TTS speech-2.8 API (native format). Returns JSON response.""" key = get_api_key() if not key: raise Exception( 'MINIMAX_API_KEY not set. ' 'Set via environment or openclaw config: ' 'openclaw config set skills.entries.minimax-tts.apiKey "sk-your-key"' ) host = get_api_host() url = f'{host}{ENDPOINT_NATIVE}' headers = { 'Content-Type': 'a ...[truncated 2825 chars]
Remediation
View remediation
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
  • Rogue AgentSelf-Modification, Session Persistence
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (14)

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

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/minimax_tts.py (reported line 93)May include surrounding context.

python
headers = {
        'Authorization': f'Bearer {key}'
    }
    response = requests.post(url, json=data, headers=headers, timeout=120)
    response.raise_for_status()

    # speech-2.6 returns binary audio directly

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

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/minimax_tts.py (reported line 126)May include surrounding context.

python
headers = {
        'Authorization': f'Bearer {key}'
    }
    response = requests.post(url, json=data, headers=headers, timeout=120)
    response.raise_for_status()

    # speech-2.6 returns binary audio directly

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/minimax_tts.py (reported line 54)May include surrounding context.

python
def get_api_key():
    """Get API key from environment or skill config."""
    key = os.environ.get('MINIMAX_API_KEY')
    if key:
        return key

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill declares capabilities that require environment access, shell execution, network access, and file writing, but it does not declare an explicit tool scope such as permissions or allowed-tools. This weakens least-privilege controls and can let the skill operate with broader access than reviewers or users expect, increasing the risk of data exfiltration or unintended system changes if the script is modified or misused.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% 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.

Content

Scanner excerpt · SKILL.md (reported line 3)May include surrounding context.

md
---
name: minimax-tts
description: Text-to-speech (TTS) generation using MiniMax API. Converts text into natural-sounding speech with support for multiple voices, adjustable speed and pitch, and multiple audio formats (MP3/WAV/PCM). Use when the user wants to convert text to speech, generate voice narration, create audio from scripts, or convert articles/essays into audio.
metadata:
  openclaw:
    emoji: "🔊"

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The file is primarily written in English, but the key access requirements and subscription guidance in lines L018-L020 are presented only in Chinese. This imposes a language requirement on users for important setup information without opt-in or an alternative English rendering, which fits the locale/language policy violation criteria.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% confidence
Finding

This request sends user text and the Bearer token to a host derived from MINIMAX_API_HOST without validating that the destination is actually MiniMax-controlled. If an attacker can influence environment variables or runtime configuration, the skill can exfiltrate both sensitive user content and API credentials to an arbitrary server.

Content

Scanner excerpt · scripts/minimax_tts.py (reported line 93)May include surrounding context.

python
headers = {
        'Authorization': f'Bearer {key}'
    }
    response = requests.post(url, json=data, headers=headers, timeout=120)
    response.raise_for_status()

    # speech-2.6 returns binary audio directly

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This code sends the input text to MiniMax via an HTTP POST request, which can expose user-provided content to a third-party service. Although the module docstring describes the tool's purpose, there is no runtime confirmation, privacy warning, or explicit disclosure near the network operation itself about transmitting user text off-system.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% confidence
Finding

The native API request has the same issue: both request payload and Authorization token are transmitted to a configurable host with no trust validation. In hostile or multi-tenant environments, this enables straightforward credential and data exfiltration by redirecting traffic through environment manipulation.

Content

Scanner excerpt · scripts/minimax_tts.py (reported line 126)May include surrounding context.

python
'Content-Type': 'application/json',
        'Authorization': f'Bearer {key}'
    }
    response = requests.post(url, json=data, headers=headers, timeout=120)
    response.raise_for_status()
    resp_json = response.json()

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The manifest describes a MiniMax API text-to-speech skill with configurable voices and formats, but does not indicate local process execution or reliance on system binaries. Spawning ffmpeg introduces a broader execution capability than simple TTS generation via API calls and is not an obvious requirement from the stated purpose alone.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/minimax_tts.py (reported line 294)May include surrounding context.

python
f.write(f"file '{tf}'\n")

                if audio_format == 'mp3':
                    subprocess.run(
                        ['ffmpeg', '-y', '-f', 'concat', '-safe', '0', '-i', concat_file,
                         '-codec:a', 'libmp3lame', '-q:a', '2', final_path],
                        check=True, capture_output=True

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/minimax_tts.py (reported line 300)May include surrounding context.

python
check=True, capture_output=True
                    )
                else:
                    subprocess.run(
                        ['ffmpeg', '-y', '-f', 'concat', '-safe', '0', '-i', concat_file, final_path],
                        check=True, capture_output=True
                    )

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The code creates directories and saves synthesized audio files automatically, either to a user-specified path or a default workspace temp directory. While saving output is part of the tool's function, there is no explicit disclosure in the CLI or code comments that files will be created automatically at the default location when --output is omitted.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

When multi-segment generation is used, the code invokes ffmpeg through subprocess.run to concatenate audio files. There is no explicit disclosure in the help text or runtime messaging that an external program will be executed as part of this workflow.

Content

No source excerpt is available for this finding.