Back to skill

Security audit

MiniMax 媒体生成 Unified MiniMax media generation skill for audio, image, and video creation with a single command entrypoint.MiniMax Skill 是一个统一的媒体生成技能,把文本转语音、文生图、文生视频三类能力收口为一个入口。安装后只需配置自己的 MINIMAX_API_KEY,即可通过统一命令生成音频、图片和视频,适合在 OpenClaw / Codex 类环境中直接调用。

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent MiniMax media generator, but its video workflow can fetch an unvalidated service-returned URL from the user’s environment.

Review before installing if your agent runs in a sensitive network or handles confidential prompts. Use a restricted runtime, avoid sending secrets or regulated data in prompts, prefer temporary API-key configuration, and be cautious with the video workflow until download URL validation and response-size limits are added.

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

Warning
Location
scripts/generate_video.py:83
Finding

Unvalidated Server-Provided Video Download URL Enables SSRF and Resource Exhaustion

Content
View full analysis

Vulnerability Details

File Location: scripts/generate_video.py, lines 83–89
Vulnerability Type: Unvalidated remote URL fetch / server-side request forgery
Risk Level: Medium

python
download_url = file_data.get("file", {}).get("download_url") or file_data.get("data", {}).get("download_url")
if not download_url:
    raise SystemExit(f"No download url returned: {json.dumps(file_data, ensure_ascii=False)}")

video_response = requests.get(download_url, timeout=300)
video_response.raise_for_status()

Technical Analysis

The script obtains download_url from the MiniMax API response and passes it directly to requests.get. It does not validate the URL scheme, hostname, resolved IP address, redirect destinations, response content type, or response size. Because requests follows redirects by default, validating only an initial URL without also validating each redirect would remain insufficient.

A malicious or compromised upstream service could return a URL targeting loopback, private, link-local, reserved, or otherwise unintended network resources. The subsequent response is also buffered in memory through video_response.content elsewhere in the same download workflow, without a maximum download-size restriction.

The MiniMax API key is not forwarded to the server identified by download_url, which limits direct credential exposure. Nevertheless, the request originates from the environment running the Skill and can therefore access network locations unavailable to an external attacker.

Attack Path

  1. A user initiates video generation through the Skill.
  2. The MiniMax API account, API service, or relevant response path is compromised or made to return an attacker-controlled download_url.
  3. The script accepts that URL without validation.
  4. requests.get sends an HTTP request from the Agent environment and follows redirects by default.
  5. The attacker directs the request to an internal ...[truncated 1046 chars]
Remediation
View remediation

Remediation Suggestions

  1. Allow only https download URLs.
  2. Enforce an allowlist of documented MiniMax-controlled CDN hostnames rather than accepting arbitrary hosts.
  3. Resolve the hostname before connecting and reject loopback, private, link-local, multicast, unspecified, and reserved IP address ranges for both IPv4 and IPv6.
  4. Disable automatic redirects or validate the scheme, hostname, and resolved address of every redirect destination before following it.
  5. Stream the response using stream=True instead of buffering the entire body.
  6. Enforce a strict maximum number of downloaded bytes and abort when the limit is exceeded.
  7. Verify that the response has an expected video media type before writing it.
  8. Write to a temporary file and atomically rename it only after validation and successful completion.
  9. Apply egress filtering at the runtime or container level to prevent access to internal and metadata networks as defense in depth.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (27)

Tainted flow: 'api_key' from os.environ.get (line 21, 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/generate_audio.py (reported line 33)May include surrounding context.

python
if args.voice_id:
        payload["voice_setting"] = {"voice_id": args.voice_id}

    response = requests.post(
        API_URL,
        headers={"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"},
        json=payload,

Tainted flow: 'api_key' from os.environ.get (line 23, 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/generate_image.py (reported line 37)May include surrounding context.

python
if args.image_file:
        payload["image_file"] = args.image_file

    response = requests.post(
        API_URL,
        headers={"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"},
        json=payload,

Tainted flow: 'api_key' from os.environ.get (line 37, 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/generate_video.py (reported line 16)May include surrounding context.

python
def post_json(url: str, api_key: str, payload: dict) -> dict:
    response = requests.post(
        url,
        headers={"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"},
        json=payload,

Tainted flow: 'task_id' from os.environ.get (line 50, credential/environment) → requests.get (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/generate_video.py (reported line 57)May include surrounding context.

python
deadline = time.time() + args.timeout
    file_id = None
    while time.time() < deadline:
        query_response = requests.get(
            QUERY_URL,
            headers={"Authorization": f"Bearer {api_key}"},
            params={"task_id": task_id},

Tainted flow: 'api_key' from os.environ.get (line 37, credential/environment) → requests.get (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/generate_video.py (reported line 77)May include surrounding context.

python
if not file_id:
        raise SystemExit("Timed out waiting for video generation")

    file_response = requests.get(
        DOWNLOAD_URL,
        headers={"Authorization": f"Bearer {api_key}"},
        params={"file_id": file_id},

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill advertises executable workflows that rely on environment variables, file output, network access, and shell execution, but it does not declare any tool/permission scope in metadata. That mismatch can cause an agent platform to invoke the skill without clear guardrails or review, increasing the chance of unintended networked execution and file writes.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The description is very broad and covers many generic media-generation use cases, which can cause the skill to activate in situations only loosely related to MiniMax. Over-broad routing increases the risk that an agent will select a networked, file-writing skill unexpectedly, exposing prompts, outputs, or API-backed actions when a narrower skill would be safer.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
75% confidence
Finding

Docker image references without a specific tag (:latest is implicit) or digest (@sha256:...) can be silently replaced by a malicious image.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/generate_audio.py (reported line 9)May include surrounding context.

python
import requests

API_URL = "https://api.minimaxi.com/v1/t2a_v2"


def main() -> int:

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/generate_image.py (reported line 10)May include surrounding context.

python
import requests

API_URL = "https://api.minimaxi.com/v1/t2a_v2"


def main() -> int:

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/generate_video.py (reported line 10)May include surrounding context.

python
import requests

API_URL = "https://api.minimaxi.com/v1/t2a_v2"


def main() -> int:

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/generate_video.py (reported line 11)May include surrounding context.

python
import requests

API_URL = "https://api.minimaxi.com/v1/t2a_v2"


def main() -> int:

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/generate_video.py (reported line 12)May include surrounding context.

python
import requests

API_URL = "https://api.minimaxi.com/v1/t2a_v2"


def main() -> int:

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/generate_audio.py (reported line 33)May include surrounding context.

python
if args.voice_id:
        payload["voice_setting"] = {"voice_id": args.voice_id}

    response = requests.post(
        API_URL,
        headers={"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"},
        json=payload,

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/generate_image.py (reported line 37)May include surrounding context.

python
if args.voice_id:
        payload["voice_setting"] = {"voice_id": args.voice_id}

    response = requests.post(
        API_URL,
        headers={"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"},
        json=payload,

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script transmits user-provided text and an API credential to an external third-party service without any inline disclosure, confirmation, or privacy notice. In an agent skill context, users may not realize that potentially sensitive prompts or content are leaving the local environment, which can create confidentiality and compliance issues.

Content

No source excerpt is available for this finding.

Tainted flow: 'audio_hex' from requests.post (line 41, network input) → pathlib.Path.write_bytes (file write)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/generate_audio.py (reported line 47)May include surrounding context.

python
output_path = Path(args.output)
    output_path.parent.mkdir(parents=True, exist_ok=True)
    output_path.write_bytes(bytes.fromhex(audio_hex))
    print(str(output_path))
    return 0

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

This code makes an outbound HTTP request to a third-party service containing the user's prompt and other request parameters, but the script provides no print/log message, confirmation, or inline warning that user-supplied content will be transmitted off-system. For code files, network calls that transmit user data should have some visible disclosure unless already clearly warned elsewhere.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/generate_video.py (reported line 16)May include surrounding context.

python
def post_json(url: str, api_key: str, payload: dict) -> dict:
    response = requests.post(
        url,
        headers={"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"},
        json=payload,

Tainted flow: 'file_id' from requests.get (line 67, network input) → requests.get (network output)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/generate_video.py (reported line 77)May include surrounding context.

python
if not file_id:
        raise SystemExit("Timed out waiting for video generation")

    file_response = requests.get(
        DOWNLOAD_URL,
        headers={"Authorization": f"Bearer {api_key}"},
        params={"file_id": file_id},

Tainted flow: 'download_url' from requests.get (line 85, network input) → requests.get (network output)

Medium
Category
Data Flow
Confidence
91% confidence
Finding

The script fetches a download_url taken from a prior network response without validating the host, scheme, or whether redirects are acceptable. If the upstream API, account, or transport path were compromised, this creates an SSRF-style primitive and could cause the agent to contact attacker-controlled infrastructure or unexpected internal resources.

Content

Scanner excerpt · scripts/generate_video.py (reported line 89)May include surrounding context.

python
if not download_url:
        raise SystemExit(f"No download url returned: {json.dumps(file_data, ensure_ascii=False)}")

    video_response = requests.get(download_url, timeout=300)
    video_response.raise_for_status()
    output_path = Path(args.output)
    output_path.parent.mkdir(parents=True, exist_ok=True)

Tainted flow: 'video_response' from requests.get (line 89, network input) → pathlib.Path.write_bytes (file write)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

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

python
video_response.raise_for_status()
    output_path = Path(args.output)
    output_path.parent.mkdir(parents=True, exist_ok=True)
    output_path.write_bytes(video_response.content)
    print(str(output_path))
    return 0

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.py (reported line 15)May include surrounding context.

python
def run(script: Path, args: list[str]) -> int:
    command = [sys.executable, str(script), *args]
    completed = subprocess.run(command)
    return completed.returncode

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The audio example hard-codes Chinese text as the default sample content, which can imply a language preference without offering alternatives or stating that the language is only illustrative. Organizational language policy findings apply when a skill appears to force a specific language without user choice.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The image example uses a Chinese prompt string without indicating that the language is optional or user-selectable. Even in examples, this can read as a default language constraint when no language choice is documented.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.