T02 · Agent Memory Poisoning
- 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: HighVulnerable 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_namecommand-line value andvoice_idreturned 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
- Validate
display_namebefore 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.
- Validate both the requested and API-returned voice identifiers against a strict pattern, such as letters, digits, underscores, and hyphens only.
- Store mappings in a structured data file such as JSON rather than inside an agent instruction document.
- 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.
- Write updates atomically through a temporary file followed by a same-filesystem replacement.
- Add tests covering multiline strings, backticks, marker injection, HTML comments, Unicode control characters, and malformed API responses.
- Validate
