T09 · Insecure Skill Coding Practices
- Location
SKILL.md:117- Finding
Shell Command Injection Through User-Controlled voice_id
- Content
View full analysis
Vulnerability Details
File Location:
SKILL.md, lines 117–132
Vulnerability Type: Shell command injection caused by unsafe interpolation
Risk Level: HighVulnerable Code
bash Once the user provides their voice_id, synthesize a welcome message so they can hear their AI voice for the first time: Default preview text (warm and personal): > "你好!这是我的 AI 声音。从今天起,我可以用这个声音说任何我想说的话了。" ```bash curl -s -X POST https://api.senseaudio.cn/v1/t2a_v2 \ -H "Authorization: Bearer $SENSEAUDIO_API_KEY" \ -H "Content-Type: application/json" \ -d "{ \"model\": \"SenseAudio-TTS-1.0\", \"text\": \"你好!这是我的 AI 声音。从今天起,我可以用这个声音说任何我想说的话了。\", \"stream\": false, \"voice_setting\": { \"voice_id\": \"<VOICE_ID>\" }, \"audio_setting\": { \"format\": \"mp3\" } }" -o preview.jsonTechnical Analysis
The workflow instructs the agent to accept a
voice_idfrom the user and place it inside a JSON document embedded directly in a double-quoted shell argument. If the placeholder is replaced through direct textual interpolation, shell constructs in the supplied value can remain active.In particular, command substitution expressions such as
$(command)and backtick expressions are evaluated inside double quotes beforecurlis executed. JSON escaping does not prevent shell evaluation. Merely surrounding the resulting JSON with double quotes is therefore insufficient to treat the user-provided identifier as data.Exploitation depends on an implementation following the documented substitution pattern directly rather than passing the identifier through a safe argument or structured JSON builder.
Attack Path
- An attacker supplies a crafted
voice_idcontaining a shell command-substitution expression. - The agent substitutes that value directly for
<VOICE_ID>in the documented shell command. - The shell evaluates the injected command substitution while const ...[truncated 940 chars]
- An attacker supplies a crafted
- Remediation
View remediation
Remediation Suggestions
- Do not construct JSON by interpolating user-controlled values into a shell command string.
- Store the supplied identifier in a shell variable and use
jq --argto encode it as JSON data. - Validate
voice_idagainst the provider's documented syntax, length, and character set before use. Validation should be defense in depth rather than the sole protection. - Pass the generated request through a file or standard input using
--data-binary, avoiding shell re-evaluation. - Use
curl --fail --silent --show-errorso HTTP failures are reported reliably. - Avoid logging the API key or full authorization header.
Example hardened construction:
bash jq -n --arg voice_id "$VOICE_ID" '{ model: "SenseAudio-TTS-1.0", text: "你好!这是我的 AI 声音。从今天起,我可以用这个声音说任何我想说的话了。", stream: false, voice_setting: {voice_id: $voice_id}, audio_setting: {format: "mp3"} }' > request.json curl --fail --silent --show-error \ -X POST https://api.senseaudio.cn/v1/t2a_v2 \ -H "Authorization: Bearer $SENSEAUDIO_API_KEY" \ -H "Content-Type: application/json" \ --data-binary @request.json \ -o preview.json
