T09 · Insecure Skill Coding Practices
- Location
scripts/transcribe.sh:73- Finding
Unvalidated and Unquoted API Host Can Expose Audio and Bearer Credentials
- Content
View full analysis
Vulnerability Details
File Location:
scripts/transcribe.sh:73-82
Vulnerability Type: Unrestricted sensitive-data destination, plaintext transport, and curl argument injection
Risk Level: Mediumbash curl -sS ${WHISPER_API_HOST:-https://api.openai.com}/v1/audio/transcriptions \ -H "Authorization: Bearer $WHISPER_API_KEY" \ -H "Accept: application/json" \ -F "file=@${in}" \ -F "model=${model}" \ -F "response_format=${response_format}" \ ${language:+-F "language=${language}"} \ ${prompt:+-F "prompt=${prompt}"} \ >"$out" echo "$out"Technical Analysis
WHISPER_API_HOSTis used directly as the destination for a request containing both the API bearer credential and the selected audio file. The script does not validate the URL scheme, hostname, port, or trust boundary. Consequently, it permits plaintext HTTP and arbitrary remote destinations.The host expansion is also unquoted:
bash ${WHISPER_API_HOST:-https://api.openai.com}/v1/audio/transcriptionsBash therefore applies word splitting and pathname expansion to a configured value. A value containing whitespace and curl options can introduce additional command-line arguments and alter curl's request behavior. Although this does not create direct shell metacharacter execution, it can manipulate curl options, destinations, configuration loading, or output handling.
The documentation explicitly demonstrates an HTTP endpoint on a local network. Bearer credentials and audio sent to such an endpoint are not protected against interception by parties capable of observing or manipulating that network.
Attack Path
- An attacker influences
WHISPER_API_HOSTthrough inherited environment configuration, Skill configuration, deployment settings, or social engineering. - The attacker sets it to a malicious HTTPS server, a plaintext HTTP endpoint, or a value containing whitespace followed by curl options.
...[truncated 1294 chars]
- An attacker influences
- Remediation
View remediation
Remediation Suggestions
-
Store the host in a variable and always quote the completed URL:
bash api_host="${WHISPER_API_HOST:-https://api.openai.com}" endpoint="${api_host%/}/v1/audio/transcriptions" curl --fail-with-body --silent --show-error \ "$endpoint" \ -H "Authorization: Bearer $WHISPER_API_KEY" \ -H "Accept: application/json" \ -F "file=@${in}" \ -F "model=${model}" \ -F "response_format=${response_format}" \ >"$out" -
Validate that the URL uses HTTPS. If plaintext HTTP is needed for local development, restrict it to explicit loopback addresses such as
127.0.0.1,localhost, or::1, and require an explicit insecure-development option. -
Consider an allowlist of approved Whisper API hosts, especially in managed or automated environments.
-
Reject host values containing whitespace, control characters, embedded credentials, fragments, or unsupported schemes. Parse the URL with a suitable URL parser rather than relying only on a regular expression.
-
Use separate, least-privileged credentials for each custom Whisper server. Do not send a production OpenAI API key to third-party or locally operated endpoints that do not require it.
-
Add
--fail-with-bodyso HTTP error responses cause a nonzero exit status, and write responses to a temporary file before atomically replacing the requested output. This prevents failed or attacker-controlled responses from silently appearing to be successful transcripts. -
Update
SKILL.mdto clearly warn that a custom host receives the complete audio file, prompt, and authorization credential, and that non-loopback HTTP endpoints expose them in plaintext.
-
