T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/tts.sh:10
- Finding
- Predictable Temporary File Allows Symlink-Based File Overwrite<![CDATA[ ## Vulnerability Details **File Location**: `scripts/tts.sh`, lines 10–37 **Vulnerability Type**: Predictable and insecure temporary-file creation **Risk Level**: Medium ### Vulnerable Code ```bash OUTPUT_FILE="/tmp/resemble_$(date +%s).mp3" if [[ -z "${RESEMBLE_API_KEY:-}" ]]; then echo "Missing RESEMBLE_API_KEY" exit 1 fi echo "🔊 Generating speech..." RESPONSE=$(curl -s -X POST "https://f.cluster.resemble.ai/synthesize" \ -H "Authorization: Bearer $RESEMBLE_API_KEY" \ -H "Content-Type: application/json" \ -d "{ \"voice_uuid\": \"$VOICE_UUID\", \"data\": \"$TEXT\", \"output_format\": \"mp3\" }") SUCCESS=$(echo "$RESPONSE" | jq -r '.success') if [[ "$SUCCESS" != "true" ]]; then echo "TTS failed:" echo "$RESPONSE" exit 1 fi echo "$RESPONSE" | jq -r '.audio_content' | base64 -d > "$OUTPUT_FILE" ``` ### Technical Analysis The output filename is derived solely from the current Unix timestamp with one-second precision. It is therefore predictable and can also collide when multiple instances execute during the same second. The file is opened using ordinary shell redirection without exclusive creation, ownership verification, or symbolic-link protection. If an attacker can create the predicted path before redirection occurs, the path may point to another file through a symbolic link. The shell then follows that link and truncates the destination before writing the decoded audio. Operating-system protections such as Linux `fs.protected_symlinks` may prevent some cross-user attacks in sticky directories. However, this does not eliminate same-user attacks, collisions between concurrent processes, or risk on systems without equivalent protections. ### Attack Path 1. An attacker determines or predicts the second in which the TTS script will run. 2. The attacker creates `/tmp/resemble_<timestamp>.mp3` as a symbolic link to a target file writable by the account executing the script. 3. The TTS request completes successf ...[truncated 828 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions Create the output through `mktemp` rather than constructing a predictable path: ```bash umask 077 OUTPUT_FILE=$(mktemp --tmpdir resemble_XXXXXXXX.mp3) trap 'rm -f -- "$OUTPUT_FILE"' EXIT ``` If the generated file must remain available after the script exits, clear the cleanup trap only after successful generation: ```bash umask 077 OUTPUT_FILE=$(mktemp --tmpdir resemble_XXXXXXXX.mp3) trap 'rm -f -- "$OUTPUT_FILE"' EXIT printf '%s' "$RESPONSE" | jq -er '.audio_content' | base64 --decode > "$OUTPUT_FILE" trap - EXIT printf 'MEDIA:%s\n' "$OUTPUT_FILE" ``` Additional hardening should include: - Use a private output directory owned by the executing account where possible. - Set restrictive permissions with `umask 077`. - Do not rely on timestamps, process IDs, or random values generated without atomic file creation. - Retain shell quoting around all path references. - Define and document a secure cleanup policy for generated audio. ]]>
