T09 · Insecure Skill Coding Practices
Warning
- Location
- SKILL.md:90
- Finding
- Unsafe User-Controlled Data Interpolation in Shell and JSON Payloads## Vulnerability Details **File Location**: `SKILL.md`, lines 90–95 and 144–155 **Vulnerability Type**: Shell command injection and malformed JSON generation **Risk Level**: Medium ### Vulnerable 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_RESP ``` Unquoted expansions are subject to shell word splitting and pathname expansion. Th ...[truncated 1850 chars]
- Remediation
- ## Remediation Suggestions Construct JSON with `jq` rather 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.
