T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/speak.sh:7
- Finding
- Unrestricted Output Path and Predictable Temporary File<![CDATA[ ## Vulnerability Details **File Location**: `scripts/speak.sh`, lines 7–17 **Vulnerability Type**: Arbitrary file overwrite and unsafe temporary-file handling **Risk Level**: Medium ### Vulnerable Code ```bash OUTPUT="${3:-/tmp/edge_tts_output.mp3}" if [ -z "$TEXT" ]; then echo "Usage: speak.sh \"Text to speak\" [voice] [output_file]" exit 1 fi /root/.local/bin/edge-tts \ --voice "$VOICE" \ --text "$TEXT" \ --write-media "$OUTPUT" ``` ### Technical Analysis The script accepts its output destination directly from the third positional argument and passes it to `edge-tts` without validating or restricting the path. If the argument is omitted, it uses the fixed, globally predictable path `/tmp/edge_tts_output.mp3`. This creates two related security weaknesses: 1. A caller can request that generated data be written to any path writable by the script's process. 2. A local attacker may pre-create the predictable default path, including as a symbolic link, before the script runs. Whether a linked destination is followed ultimately depends on the file-opening behavior of the external `edge-tts` executable, but the script performs no checks to prevent this condition. The fixed path also creates a race and collision condition: concurrent invocations can overwrite or return one another's output. The quoted shell expansions prevent shell command injection through these arguments, but quoting does not mitigate filesystem path manipulation. ### Attack Path 1. An attacker supplies a chosen writable path as the third argument, or pre-creates `/tmp/edge_tts_output.mp3` as a symbolic link to another file writable by the process. 2. The Agent invokes `scripts/speak.sh` with attacker-influenced input or uses the predictable default output path. 3. The script forwards the path unchanged through `--write-media`. 4. `edge-tts` creates or overwrites the destination when its normal file-writing behavior permits it. 5. Existing writable content may be repl ...[truncated 694 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Create a unique output file using `mktemp`, preferably inside a private directory owned by the executing account: ```bash OUTPUT_DIR="${XDG_RUNTIME_DIR:-/tmp}/edge-tts-${UID}" mkdir -p -- "$OUTPUT_DIR" chmod 700 -- "$OUTPUT_DIR" if [ -n "${3:-}" ]; then echo "Caller-selected output paths are not permitted." >&2 exit 1 fi OUTPUT="$(mktemp --tmpdir="$OUTPUT_DIR" 'speech.XXXXXX.mp3')" chmod 600 -- "$OUTPUT" ``` - If caller-selected destinations are required, canonicalize the requested path and allow writes only beneath a dedicated, Agent-owned output directory. - Reject symbolic links and non-regular existing destinations. Where supported, use file-opening semantics equivalent to `O_NOFOLLOW` and exclusive creation. - Avoid a shared fixed filename so concurrent invocations cannot overwrite or disclose each other's output. - Run the Skill as an unprivileged account with access only to its dedicated output directory. - Delete generated files after they have been delivered, unless retention is explicitly required. - Check the exit status of `edge-tts` before printing or sending the output path, and remove partial output following a failed invocation. ]]>
