T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/transcribe.sh:75
- Finding
- Arbitrary Local File Disclosure Through Unsafe curl Multipart Form Values<![CDATA[ ## Vulnerability Details **File Location**: `scripts/transcribe.sh`, lines 75–78 **Vulnerability Type**: Local file disclosure through curl form-value interpretation **Risk Level**: Medium ### Vulnerable Code ```bash -F "model=${model}" \ -F "response_format=${response_format}" \ ${language:+-F "language=${language}"} \ ${prompt:+-F "prompt=${prompt}"} \ ``` ### Technical Analysis The `model`, `language`, and `prompt` variables can be controlled through command-line options. They are passed to `curl` using `-F`, which applies special multipart-form semantics to values beginning with `@`. Such a value is interpreted as a local filename whose contents should be read and included in the multipart request. Consequently, a value such as `--prompt @/etc/passwd` can cause `curl` to read the specified local file and transmit its contents to `https://api.groq.com/openai/v1/audio/transcriptions`. The remote API may reject the malformed field, but the sensitive content has already been transmitted by that point. The audio-file field intentionally requires `-F "file=@${in}"`; however, scalar fields such as the model, language, response format, and prompt should not use file-upload interpretation. ### Attack Path 1. An attacker gains the ability to influence arguments passed to `transcribe.sh`, such as through an automated agent workflow or a wrapper that forwards untrusted values. 2. The attacker supplies a scalar option beginning with `@`, for example: ```bash ./scripts/transcribe.sh audio.m4a --prompt @/home/user/.ssh/id_rsa ``` 3. The script assigns the attacker-controlled value to `prompt`. 4. `curl -F` interprets `@/home/user/.ssh/id_rsa` as a request to read that local file. 5. The file contents are inserted into the multipart request and transmitted to Groq's API endpoint. 6. Even if the endpoint rejects the request, disclosure has already occurred. ### Impact Assessment This issue permits disclosure of arbitrary local files re ...[truncated 472 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions Use `--form-string` for every scalar multipart field so values beginning with `@`, `<`, or other special characters are treated as literal strings. Retain `-F` only for the intended audio-file upload. A robust implementation can construct the curl arguments with a Bash array: ```bash curl_args=( -sS "https://api.groq.com/openai/v1/audio/transcriptions" -H "Authorization: Bearer $GROQ_API_KEY" -H "Accept: application/json" -F "file=@${in}" --form-string "model=${model}" --form-string "response_format=${response_format}" ) if [[ -n "$language" ]]; then curl_args+=(--form-string "language=${language}") fi if [[ -n "$prompt" ]]; then curl_args+=(--form-string "prompt=${prompt}") fi curl "${curl_args[@]}" >"$out" ``` Using an argument array also prevents unintended word splitting and preserves prompts containing spaces or shell metacharacters. As defense in depth: 1. Validate `model` against an explicit allowlist of supported model identifiers. 2. Validate `language` against the expected language-code format. 3. Add regression tests using values such as `@/etc/passwd` and verify that no local file content is included in the request. 4. Run the Skill with the minimum filesystem permissions required for its intended operation. ]]>
