T09 · Insecure Skill Coding Practices
Warning
- Location
- SKILL.md:251
- Finding
- Synthesized Audio Remains in Persistent Temporary Files<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 251–259 **Vulnerability Type**: Sensitive-data retention through unsafe temporary-file lifecycle **Risk Level**: Medium ### Vulnerable Code ```python with tempfile.NamedTemporaryFile(suffix=".mp3", delete=False) as f: f.write(audio_bytes) tmp = f.name for cmd in [["afplay", tmp], ["play", tmp], ["mpg123", tmp]]: try: subprocess.run(cmd, check=True, capture_output=True) return except (FileNotFoundError, subprocess.CalledProcessError): continue ``` ### Technical Analysis The synthesized MP3 is created with `delete=False`, but the function does not remove it after successful playback or after all playback attempts fail. Every invocation can therefore leave an audio file in the operating system's temporary directory. The audio may contain private message contents, health or medication reminders, family information, weather locations, or AI conversation responses. Although `NamedTemporaryFile` normally creates files with restrictive permissions, the data remains available to processes operating under the same account, privileged local users, forensic tools, backup systems, or later compromise of the host account. The fixed command arrays do not introduce command injection because no shell is used and the executable names are not derived from user input. The vulnerability is specifically the failure to manage the temporary file's lifecycle. ### Attack Path 1. A user submits speech containing private or health-related information. 2. The assistant generates a response that repeats or references that information. 3. The response is sent to the TTS service, and the returned audio is written to a temporary MP3 with `delete=False`. 4. Playback succeeds and the function returns, or all playback commands fail. 5. No cleanup operation removes the MP3. 6. A process with access to the same account, a privileged local user, or an attacker who later compromises ...[truncated 562 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions Place playback inside a `try` block and remove the temporary file in a `finally` block so cleanup occurs on success, failure, and unexpected exceptions. ```python tmp = None try: with tempfile.NamedTemporaryFile(suffix=".mp3", delete=False) as f: f.write(audio_bytes) tmp = f.name for cmd in [["afplay", tmp], ["play", tmp], ["mpg123", tmp]]: try: subprocess.run(cmd, check=True, capture_output=True) return except (FileNotFoundError, subprocess.CalledProcessError): continue finally: if tmp: try: os.remove(tmp) except FileNotFoundError: pass ``` Additional hardening measures: - Prefer streaming audio directly from memory or standard input when supported by the playback tool. - Explicitly retain restrictive owner-only file permissions. - Avoid logging temporary paths or synthesized private content. - Add a startup cleanup routine for stale files created by earlier crashes. - Define and document a minimal retention policy for voice data. ]]>
