T09 · Insecure Skill Coding Practices
- Location
scripts/kai_realtime.sh:32- Finding
Unescaped User Input Allows JSON Request Manipulation
- Content
View full analysis
Vulnerability Details
File Location:
scripts/kai_realtime.sh, lines 32–41
Vulnerability Type: Unsafe JSON construction with untrusted input
Risk Level: MediumVulnerable Code
bash TEXT="$2" VOICE_ID="${KAI_ENGLISH_VOICE_ID:-moss_audio_2b525bea-10da-11f1-bd2a-3a1ec25b94c4}" if [ -z "$TEXT" ]; then echo "Usage: $0 --stream \"text\"" exit 1 fi echo "Streaming text: $TEXT" # For real streaming, would use WebSocket here # For now, fallback to REST API RESP=$(curl -s -X POST "https://api.minimax.io/v1/t2a_v2" \ -H "Authorization: Bearer ${API_KEY}" \ -H "Content-Type: application/json" \ -d "{\"model\":\"speech-02-turbo\",\"text\":\"$TEXT\",\"stream\":false,\"output_format\":\"hex\",\"voice_setting\":{\"voice_id\":\"$VOICE_ID\",\"speed\":1},\"audio_setting\":{\"sample_rate\":32000}}")Technical Analysis
The script constructs a JSON request by directly interpolating
TEXTandVOICE_IDinto a double-quoted string. Neither value is encoded using a JSON-aware serializer.Shell quoting prevents these values from being interpreted as shell commands, so this is not shell command injection. However, quotation marks, backslashes, control characters, or JSON delimiters in either value can terminate the intended JSON string, add properties, create duplicate properties, or make the request invalid.
The concrete result depends on how the MiniMax endpoint handles unknown or duplicate JSON properties. At minimum, legitimate text containing quotation marks or other special characters can cause malformed requests. If the service accepts injected or duplicate properties, crafted input may alter request behavior.
Attack Path
- An attacker or untrusted caller controls the second argument passed to
--stream. - The attacker includes JSON syntax, such as embedded quotation marks and additional properties, in that argument.
- The script inserts the value directly i ...[truncated 925 chars]
- An attacker or untrusted caller controls the second argument passed to
- Remediation
View remediation
Remediation Suggestions
Construct the payload with a JSON-aware serializer rather than shell string interpolation. For example, use
jq:bash PAYLOAD=$(jq -n \ --arg text "$TEXT" \ --arg voice_id "$VOICE_ID" \ '{ model: "speech-02-turbo", text: $text, stream: false, output_format: "hex", voice_setting: { voice_id: $voice_id, speed: 1 }, audio_setting: { sample_rate: 32000 } }') RESP=$(curl --fail-with-body --silent --show-error \ -X POST "https://api.minimax.io/v1/t2a_v2" \ -H "Authorization: Bearer ${API_KEY}" \ -H "Content-Type: application/json" \ --data-binary "$PAYLOAD")Additionally:
- Validate
VOICE_IDagainst the character set and length accepted by MiniMax. - Apply a reasonable maximum length to
TEXT. - Handle HTTP failures explicitly with
--fail-with-body. - Avoid printing sensitive user-supplied text unless operational logging requires it.
- Validate
