T09 · Insecure Skill Coding Practices
- Location
scripts/gen_voice_lines.py:51- Finding
Arbitrary File Write Through TTS Output Name Path Traversal
- Content
View full analysis
2 and parts[2] else def_rate pitch = parts[3] if len(parts) > 3 and parts[3] else def_pitch return (name, text, rate, pitch) async def gen(outdir: str, lines, voice: str): os.makedirs(outdir, exist_ok=True) for name, text, rate, pitch in lines: out = os.path.join(outdir, f"{name}.mp3") tts = edge_tts.Communicate(text, voice=voice, rate=rate, pitch=pitch) await tts.save(out) ``` ### Technical Analysis The filename component of each `--voice` argument is accepted without rejecting absolute paths, parent-directory components, or path separators. It is passed directly to `os.path.join()` and then to `edge_tts.save()`. `os.path.join()` does not enforce containment. A value such as `../../target` produces a path outside the intended output directory. An absolute path can also cause the output directory component to be discarded on supported platforms. No canonical-path containment check or symlink protection is applied. The content written is constrained to the MP3 generated by the TTS provider, but the attacker can still select the destination path. ### Attack Path 1. An attacker controls or influences a custom voice argument processed by the Skill. 2. The attacker supplies a name containing traversal components, for example: ```text --voice "../../target:attacker-selected dialogue" ``` 3. `parse_voice_arg()` accepts `../../target` ...[truncated 594 chars]- Remediation
View remediation
