T09 · Insecure Skill Coding Practices
- Location
SKILL.md:90- Finding
Unsafe User-Controlled Data Interpolation in Shell and JSON Payloads
- Content
View full analysis
Vulnerability Details
File Location:
SKILL.md, lines 90–95 and 144–155
Vulnerability Type: Shell command injection and malformed JSON generation
Risk Level: MediumVulnerable Code
bash LYRICS_RESP=$(curl -s -X POST "https://api.senseaudio.cn/v1/song/lyrics/create" \ -H "Authorization: Bearer $SENSEAUDIO_API_KEY" \ -H "Content-Type: application/json" \ -d "{\"prompt\": \"<PROMPT>\", \"provider\": \"sensesong\"}") TASK_ID=$(echo $LYRICS_RESP | jq -r '.task_id // empty')bash SONG_RESP=$(curl -s -X POST "https://api.senseaudio.cn/v1/song/music/create" \ -H "Authorization: Bearer $SENSEAUDIO_API_KEY" \ -H "Content-Type: application/json" \ -d "{ \"model\": \"sensesong\", \"lyrics\": \"<APPROVED_LYRICS>\", \"title\": \"<new theme + based on original title>\", \"vocal_gender\": \"<f|m>\", \"style\": \"<INFERRED_STYLE>\" }") SONG_TASK=$(echo $SONG_RESP | jq -r '.task_id')Technical Analysis
The instructions place prompt, lyrics, title, and style placeholders directly inside double-quoted shell arguments used to construct JSON. These values can contain user-controlled content. If an agent implements the documented commands by performing direct textual substitution, shell-sensitive sequences such as command substitutions, quotes, backslashes, or newlines become part of the generated shell source.
For example, a value containing a command substitution such as
$(command)may be evaluated by the shell when inserted directly into the command template. Embedded quotation marks and backslashes can also terminate or alter JSON string values, resulting in malformed payloads or unintended API parameters.The API responses are subsequently processed using unquoted expansions:
bash echo $LYRICS_RESP echo $SONG_RESPUnquoted expansions are subject to shell word splitting and pathname expansion. Th ...[truncated 1850 chars]
- Remediation
View remediation
Remediation Suggestions
Construct JSON with
jqrather than interpolating data into shell source:bash PAYLOAD=$(jq -n \ --arg prompt "$PROMPT" \ --arg provider "sensesong" \ '{prompt: $prompt, provider: $provider}') LYRICS_RESP=$(curl --fail-with-body --silent --show-error \ -X POST "https://api.senseaudio.cn/v1/song/lyrics/create" \ -H "Authorization: Bearer $SENSEAUDIO_API_KEY" \ -H "Content-Type: application/json" \ --data-binary "$PAYLOAD")Apply the same approach to the music request:
bash PAYLOAD=$(jq -n \ --arg model "sensesong" \ --arg lyrics "$APPROVED_LYRICS" \ --arg title "$TITLE" \ --arg vocal_gender "$VOCAL_GENDER" \ --arg style "$INFERRED_STYLE" \ '{ model: $model, lyrics: $lyrics, title: $title, vocal_gender: $vocal_gender, style: $style }')Process responses without unquoted expansion:
bash TASK_ID=$(printf '%s' "$LYRICS_RESP" | jq -r '.task_id // empty')Keep user-controlled content in data variables and never generate executable shell source through raw textual substitution. Validate enumerated fields such as vocal gender, impose reasonable length limits, and reject control characters where they are not required.
