Back to skill

Security audit

Mimimax Voice Clone +TTS

Security checks for vulnerabilities and agentic risk

Overview

This voice-cloning skill mostly matches its stated purpose, but its write-back feature can persist unsanitized text into skill instruction files and can be pointed outside its documented file scope.

Review this skill before installing. It legitimately needs a MiniMax API key and sends user audio and text to MiniMax, but only run it with trusted voice names, display names, and registry paths. Prefer a version that validates or escapes mapping fields, removes or restricts --skill-md, and pins dependencies.

Vulnerability Patterns
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (3)

T02 · Agent Memory Poisoning

Error
Location
scripts/minimax_voice_clone_tts.py:199
Finding

Persistent Markdown Injection Through Unsanitized Voice Mapping Fields

Content
View full analysis

Vulnerability Details

File Location: scripts/minimax_voice_clone_tts.py, lines 199–205, 225–230, and 344–346
Vulnerability Type: Persistent content injection into the Skill document
Risk Level: High

Vulnerable Code

python
rows = [ln for ln in middle.strip("\n").splitlines() if is_mapping_line(ln)]
row_prefix = f"- `{display_name}`:"
now = dt.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
new_row = f"- `{display_name}`: `{voice_id}` (updated: {now})"

replaced = False
for i, row in enumerate(rows):
    if row.strip().startswith(row_prefix):
        rows[i] = new_row
        replaced = True
        break
if not replaced:
    rows.append(new_row)

# Sort by display name (case-insensitive for ASCII, natural for Chinese)
rows_sorted = sorted(rows, key=lambda x: (parse_line(x) or ("", ""))[0].lower())
rebuilt_middle = "\n".join(rows_sorted)
rebuilt = (
    f"{before}{VOICES_START}\n"
    f"{rebuilt_middle}\n"
    f"{VOICES_END}{after}"
)
skill_md_path.write_text(rebuilt, encoding="utf-8")

The write operation is invoked after voice cloning:

python
registry_key = args.display_name if args.display_name else args.voice_name
update_skill_registry(skill_md, registry_key, voice_id)
print(f"Voice mapping written to: {skill_md} ({registry_key} -> {voice_id})")

Technical Analysis

The display_name command-line value and voice_id returned by the remote API are embedded directly into a Markdown line. The implementation does not reject line breaks, control characters, backticks, HTML comments, mapping delimiters, or other Markdown content.

Because the destination is SKILL.md, this is more consequential than ordinary formatting corruption. Skill documents can be loaded as agent instructions in later sessions. An attacker-controlled multiline display name could terminate the intended mapping line and insert durable Markdown instructions into the document.

The A ...[truncated 1372 chars]

Remediation
View remediation

Remediation Suggestions

  1. Validate display_name before any network request or file write:
    • Reject carriage returns, line feeds, null bytes, and all control characters.
    • Reject or escape backticks and HTML comment delimiters.
    • Enforce a documented maximum length.
    • Prefer a conservative Unicode-aware allowlist suitable for display names.
  2. Validate both the requested and API-returned voice identifiers against a strict pattern, such as letters, digits, underscores, and hyphens only.
  3. Store mappings in a structured data file such as JSON rather than inside an agent instruction document.
  4. If Markdown storage must be retained, use a dedicated escaping routine and parse the completed output to verify that exactly one mapping entry was added.
  5. Write updates atomically through a temporary file followed by a same-filesystem replacement.
  6. Add tests covering multiline strings, backticks, marker injection, HTML comments, Unicode control characters, and malformed API responses.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/minimax_voice_clone_tts.py:301
Finding

User-Controlled Registry Path Permits Modification Outside the Skill Directory

Content
View full analysis

Vulnerability Details

File Location: scripts/minimax_voice_clone_tts.py, lines 225–230, 301–306, 316, and 344–346
Vulnerability Type: Unrestricted file write destination
Risk Level: Medium

Vulnerable Code

The destination path is exposed as a user-controlled command-line option:

python
parser.add_argument(
    "--skill-md",
    type=str,
    default=str(Path(__file__).resolve().parents[1] / "SKILL.md"),
    help="Path to SKILL.md for writing back cloned voice mapping.",
)

The supplied path is resolved but not restricted to the project:

python
skill_md = Path(args.skill_md).expanduser().resolve()

After cloning, the selected file is passed to the registry writer:

python
registry_key = args.display_name if args.display_name else args.voice_name
update_skill_registry(skill_md, registry_key, voice_id)
print(f"Voice mapping written to: {skill_md} ({registry_key} -> {voice_id})")

The target is then overwritten:

python
rebuilt = (
    f"{before}{VOICES_START}\n"
    f"{rebuilt_middle}\n"
    f"{VOICES_END}{after}"
)
skill_md_path.write_text(rebuilt, encoding="utf-8")

Technical Analysis

The Skill documentation states that the script only reads and writes this Skill’s SKILL.md. The implementation does not enforce that boundary. --skill-md accepts an arbitrary path, and calling resolve() only canonicalizes the path; it does not establish containment or authorization.

Any writable file containing the expected CLONED_VOICES marker strings can be reconstructed and overwritten. This exceeds the minimum file access needed for the declared functionality. The absence of an exact-path check also means a caller can deliberately select another Skill document or unrelated marked file.

Attack Path

  1. The attacker identifies a file writable by the current user that contains the expected start and end markers.
  2. The attacker invokes t ...[truncated 1005 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove the --skill-md option if alternate registry locations are not essential.
  2. Calculate the canonical packaged path internally and require the destination to equal:
    python
    expected = (Path(__file__).resolve().parents[1] / "SKILL.md").resolve()
    
  3. If configurable locations are required, restrict them to an explicitly approved directory and verify containment with Path.relative_to().
  4. Refuse symbolic-link destinations and recheck the target immediately before replacement to reduce link-based race risks.
  5. Use an atomic write with restrictive permissions and preserve the original file if validation fails.
  6. Clearly document any intentionally supported external registry paths and request explicit user confirmation before modifying them.

T08 · Insecure Dependencies

Note
Location
requirements.txt:2
Finding

Open-Ended Dependency Version Prevents Reproducible Installation

Content
View full analysis

Vulnerability Details

File Location: requirements.txt, line 2
Vulnerability Type: Unpinned third-party dependency
Risk Level: Low

Vulnerable Code

text
requests>=2.28.0

Technical Analysis

The dependency declaration sets only a minimum version and no upper bound, exact version, lock file, or package hash. Consequently, installations performed at different times may resolve to different releases that were not part of this audit.

The package name is the legitimate requests dependency; the audit found no evidence that the current declaration intentionally references a malicious or typosquatted package. The risk is that an open-ended constraint delegates selection to the package index at installation time, weakening build reproducibility and increasing exposure to a future compromised, vulnerable, or incompatible release.

Attack Path

  1. A user installs the Skill dependencies using pip install -r requirements.txt.
  2. The package resolver selects any available requests release satisfying >=2.28.0.
  3. A release published after this audit is installed without project-level review.
  4. If that release or one of its resolved transitive dependencies is compromised or vulnerable, its code executes in the Skill’s Python environment when imported or used.

This is a supply-chain hardening weakness rather than evidence of an existing malicious dependency.

Impact Assessment

A compromised dependency would execute with the privileges of the Python process and could access the MiniMax credential present in the environment, user-provided audio, synthesis text, output files, and other resources available to that process.

No specific compromised version or currently exploitable dependency vulnerability was identified in the reviewed project. The confirmed impact is loss of deterministic, auditable dependency resolution.

Remediation
View remediation

Remediation Suggestions

  1. Pin requests to a specific reviewed version.
  2. Generate a lock file that includes all transitive dependencies.
  3. Require hashes during installation, for example through a hash-locked requirements file and pip --require-hashes.
  4. Use an automated dependency-update process that runs tests and security review before changing pinned versions.
  5. Periodically scan the complete resolved dependency set for known vulnerabilities.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (11)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
ed or existing voices, and (4) updating the cloned-voice mapping block in this `SKILL.md`. The script only reads/writes this skill’s `SKILL.md`; it does not rea

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
ed or existing voices, and (4) updating the cloned-voice mapping block in this `SKILL.md`. The script only reads/writes this skill’s `SKILL.md`; it does not rea

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
ed or existing voices, and (4) updating the cloned-voice mapping block in this `SKILL.md`. The script only reads/writes this skill’s `SKILL.md`; it does not rea

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill documentation describes capabilities to read environment variables, perform network requests to the MiniMax API, and read/write its own SKILL.md, but it does not declare an explicit tool scope such as permissions or allowed-tools. This creates a security governance gap: an agent or reviewer cannot enforce least privilege from the manifest alone, increasing the risk of unintended credential access, network egress, or file modification if the implementation changes or is invoked in a broader runtime context.

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

python
import requests

UPLOAD_URL = "https://api.minimax.io/v1/files/upload"
CLONE_URL = "https://api.minimax.io/v1/voice_clone"
TTS_URL = "https://api.minimax.io/v1/t2a_v2"

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

python
import requests

UPLOAD_URL = "https://api.minimax.io/v1/files/upload"
CLONE_URL = "https://api.minimax.io/v1/voice_clone"
TTS_URL = "https://api.minimax.io/v1/t2a_v2"

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

python
import requests

UPLOAD_URL = "https://api.minimax.io/v1/files/upload"
CLONE_URL = "https://api.minimax.io/v1/voice_clone"
TTS_URL = "https://api.minimax.io/v1/t2a_v2"

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

python
body["text"] = preview_text

    headers = {"Content-Type": "application/json", **_auth_headers(api_key)}
    resp = requests.post(CLONE_URL, headers=headers, json=body, timeout=120)
    resp.raise_for_status()
    payload = resp.json()
    _ensure_ok_base_resp(payload, "create cloned voice")

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

python
}

    headers = {"Content-Type": "application/json", **_auth_headers(api_key)}
    resp = requests.post(TTS_URL, headers=headers, json=body, timeout=180)
    resp.raise_for_status()
    payload = resp.json()
    _ensure_ok_base_resp(payload, "text to speech")

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
94% confidence
Finding

The dependency is specified as requests>=2.28.0, which permits installation of many different future or current versions without reproducibility guarantees. This weakens supply-chain hygiene because builds may silently resolve to a vulnerable or incompatible release, making security review and incident response harder.

Content

Scanner excerpt · requirements.txt (reported line 2)May include surrounding context.

text
# MiniMax voice clone + TTS script
requests>=2.28.0

Unverifiable Dependency: requests has 16 known advisory(ies) (CVE-2014-1830 (Exposure of Sensitive Information to an Unauthorized Actor in Requests); CVE-2024-47081 (Requests vulnerable to .netrc credentials leak via malicious URLs); CVE-2024-35195 (Requests `Session` object does not verify requests after making first request wi) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
89% confidence
Finding

Because requests is not pinned, it is not possible to verify whether the installed version includes fixes for known CVEs affecting some releases of the library. In a skill that likely performs outbound API calls to a voice/TTS service, use of a vulnerable HTTP client could expose credentials, request metadata, or transport security assumptions depending on the resolved version and usage.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.