T09 · Insecure Skill Coding Practices
- Location
SKILL.md:66- Finding
Shell Command Injection Through Unsafely Interpolated TTS Text
- Content
View full analysis
", "stream": false, "voice_setting": { "voice_id": "" }, "audio_setting": { "format": "mp3" } }' -o response.json # Decode hex audio to mp3 jq -r '.data.audio' response.json | xxd -r -p > output.mp3 ``` ### Technical Analysis The documented command places the `` and `` placeholders inside a single-quoted shell argument. If an implementation follows these instructions by directly replacing the placeholders with user-controlled values, a single quote in the supplied text terminates the shell string. After terminating the quoted string, an attacker can introduce shell expansions, separators, redirections, or additional commands. This is not only a JSON-escaping problem: the shell interprets the injected content before `curl` receives the request. For example, text containing the following value can trigger command substitution while preserving the surrounding shell word: ```text '$(touch /tmp/injected)' ``` After direct substitution, the shell closes the original single-quoted string, evaluates `$(touch /tmp/injected)`, and then resumes the quoted argument. More harmful commands could read accessible files, modify project data, invoke other installed programs, or transmit environment variables such as `SENSEAUDIO_API_KEY`. Ordinary text containing apostrophes can also break the command or produce malformed JSON even when no malicious exploitation is attempted. ### Attack Path 1. An attacker supplies text for speech synthesis containing a single quote followed by shell synta ...[truncated 1483 chars]- Remediation
View remediation
request.json curl --fail-with-body --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 response.json ``` Additional hardening measures should include: 1. Pass dynamic values to `jq` exclusively through `--arg`; never build shell commands with `eval`, string concatenation, or direct placeholder replacement. 2. Restrict `VOICE_ID` to the documented allowlist rather than accepting arbitrary values. 3. Verify that `.base_resp.status_code == 0` and that `.data.audio` is a valid string before decoding it. 4. Create temporary request and response files with restrictive permissions, preferably using `mktemp` and `umask 077`. 5. Quote every shell variable expansion and use fixed output directories. 6. Derive descriptive filenames through a strict safe-character allowlist rather than using raw user text as a path. 7. Run the skill with least privilege and limit its filesystem and network access to reduce the consequences of any future command-injection flaw. ]]>
