T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/tts.sh:38
- Finding
- Unvalidated CLI Arguments Permit JSON Request Injection<![CDATA[ ## Vulnerability Details **File Location**: `scripts/tts.sh`, lines 38–48 **Vulnerability Type**: Unsafe JSON construction using unvalidated user-controlled values **Risk Level**: Medium ### Vulnerable Code ```bash PAYLOAD=$(cat <<EOF { "text": $(echo "$TEXT" | jq -Rs .), "voice_id": "$VOICE", "audio_config": { "audio_encoding": "MP3", "speaking_rate": $RATE }, "temperature": $TEMP, "model_id": "$MODEL" } EOF ) ``` ### Technical Analysis The script safely encodes `TEXT` with `jq`, but directly interpolates the user-controlled `VOICE`, `MODEL`, `RATE`, and `TEMP` arguments into a JSON document. `VOICE` and `MODEL` are placed inside JSON strings without JSON escaping. An argument containing quotation marks and additional JSON syntax can terminate the original string and inject new properties. `RATE` and `TEMP` are inserted as unrestricted raw JSON values, allowing a caller to introduce unexpected JSON structures or additional fields. The resulting payload is transmitted to the Inworld API using the victim's `INWORLD_API_KEY`. This issue does not result in shell command execution because the variables remain quoted when passed to `curl`, but it allows manipulation of the authenticated API request and can also produce malformed requests. ### Attack Path 1. An attacker gains the ability to influence arguments passed to `tts.sh`, such as through an application or Agent that invokes the script with untrusted synthesis options. 2. The attacker supplies a crafted `--voice`, `--model`, `--rate`, or `--temp` argument containing JSON syntax. 3. The script interpolates the value into `PAYLOAD` without appropriate encoding or type validation. 4. The modified payload is sent to `https://api.inworld.ai` under the configured API credential. 5. Depending on what the API accepts, the request may contain unintended fields, consume API quota, generate unexpected output, or fail in an attacker-controlled manner. ### Impact Assessment The vuln ...[truncated 475 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions Construct the complete payload through `jq` rather than interpolating values into a here-document. Pass strings using `--arg` and validated numeric values using `--argjson`. For example: ```bash [[ "$RATE" =~ ^([0-9]+([.][0-9]+)?|[.][0-9]+)$ ]] || { echo "Invalid speaking rate" >&2; exit 1; } [[ "$TEMP" =~ ^([0-9]+([.][0-9]+)?|[.][0-9]+)$ ]] || { echo "Invalid temperature" >&2; exit 1; } awk -v value="$RATE" 'BEGIN { exit !(value >= 0.5 && value <= 2.0) }' || { echo "Speaking rate must be between 0.5 and 2.0" >&2; exit 1; } awk -v value="$TEMP" 'BEGIN { exit !(value >= 0.1 && value <= 2.0) }' || { echo "Temperature must be between 0.1 and 2.0" >&2; exit 1; } PAYLOAD=$(jq -n \ --arg text "$TEXT" \ --arg voice "$VOICE" \ --arg model "$MODEL" \ --argjson rate "$RATE" \ --argjson temp "$TEMP" \ '{ text: $text, voice_id: $voice, audio_config: { audio_encoding: "MP3", speaking_rate: $rate }, temperature: $temp, model_id: $model }') ``` Also validate voice and model identifiers against documented formats or an allowlist when possible. Reject missing values for options such as `--voice` before attempting to read `$2`. ]]>
