T09 · Insecure Skill Coding Practices
- Location
scripts/tts.py:219- Finding
Predictable Temporary File Creation Enables Local File Clobbering
- Content
View full analysis
Vulnerability Details
File Location:
scripts/tts.py, lines 219-221
Vulnerability Type: Insecure temporary file creation
Risk Level: MediumVulnerable Code:
python tmp_wav = tempfile.mktemp(suffix=".wav") save_wav(audio_bytes, tmp_wav) convert_to_opus(tmp_wav, output)Technical Analysis
The application uses
tempfile.mktemp()to generate a temporary WAV path. This function returns a filename without atomically creating or opening the corresponding file. A time-of-check-to-time-of-use window therefore exists between generating the path and opening it throughsave_wav().A local attacker who can monitor or predict temporary filenames may create a symbolic link at the selected path before
save_wav()opens it. Becausewave.open(output_path, "wb")ultimately opens the path for writing, it may follow the attacker-created symbolic link and truncate or overwrite its target.The vulnerable path is reached whenever Opus output is requested. Although the temporary file is removed in a
finallyblock, cleanup occurs only after the potentially unsafe write and does not prevent exploitation.Attack Path
- The victim runs the skill with
--format opus. - The script calls
tempfile.mktemp()and receives an unreserved temporary filename. - A local attacker identifies or predicts that filename before
save_wav()opens it. - The attacker creates a symbolic link from the temporary filename to a file writable by the victim process.
save_wav()follows the symbolic link and opens the target in write mode.- The target is truncated and replaced with generated audio data.
- If the skill runs under a privileged account, the overwrite may affect privileged files that the attacker could not directly modify.
Impact Assessment
Successful exploitation can corrupt or overwrite arbitrary files writable by the account executing the skill. The vulnerability does not independently gr ...[truncated 479 chars]
- The victim runs the skill with
- Remediation
View remediation
Remediation Suggestions
Replace
tempfile.mktemp()with an API that atomically creates the temporary file:python fd, tmp_wav = tempfile.mkstemp(suffix=".wav") os.close(fd) try: save_wav(audio_bytes, tmp_wav) convert_to_opus(tmp_wav, output) finally: if os.path.exists(tmp_wav): os.unlink(tmp_wav)Alternatively, use
tempfile.NamedTemporaryFile(suffix=".wav", delete=False)and close it before passing its path toffmpeg.Additional hardening should include:
- Retaining restrictive permissions on the temporary file.
- Creating temporary files only in a trusted directory.
- Avoiding any unlink-and-reopen sequence that would recreate the race.
- Running the skill with the least privileged account necessary.
- Preserving cleanup in a
finallyblock.
