T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/transcribe.sh:69
- Finding
- Unrestricted API Base URL Can Expose the API Key and Audio Data<![CDATA[ ## Vulnerability Details **File Location**: `scripts/transcribe.sh`, lines 69–108 **Vulnerability Type**: Unvalidated external endpoint configuration and sensitive-data disclosure **Risk Level**: High ### Vulnerable Code ```bash api_base="${OPENAI_BASE_URL:-https://api.openai.com/v1}" api_base="${api_base%/}" request_format="text" if [[ "$json_output" == "1" ]]; then request_format="json" fi diarize=0 case "$model" in gpt-4o-transcribe | gpt-4o-mini-transcribe | gpt-4o-mini-transcribe-*) request_format="json" ;; gpt-4o-transcribe-diarize) diarize=1 request_format="diarized_json" ;; esac if [[ "$diarize" == "1" && "$prompt" != "" ]]; then echo "--prompt is not supported with gpt-4o-transcribe-diarize" >&2 exit 2 fi target="$out" tmp="" if [[ "$json_output" == "0" && ( "$request_format" == "json" || "$request_format" == "diarized_json" ) ]]; then tmp="$(mktemp)" trap '[[ "$tmp" == "" ]] || rm -f "$tmp"' EXIT target="$tmp" fi curl_args=( -sS "${api_base}/audio/transcriptions" -H "Authorization: Bearer $OPENAI_API_KEY" -H "Accept: application/json" -F "file=@${in}" -F "model=${model}" -F "response_format=${request_format}" ) ``` The corresponding configurable-proxy behavior is documented in `SKILL.md` at lines 29 and 58. ### Technical Analysis The script obtains the transcription endpoint directly from the environment variable `OPENAI_BASE_URL`. It removes a trailing slash but performs no validation of the URL scheme, destination host, port, or embedded credentials. The resulting endpoint is passed to `curl` together with two sensitive assets: 1. `OPENAI_API_KEY`, transmitted in the `Authorization` header. 2. The complete user-selected audio file, transmitted as multipart form data. Consequently, any party capable of controlling the process environment or active OpenClaw configuration can redirect the request to an arbitrary server. The implementation also permits plaintext `http://` endpoints, ...[truncated 1897 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Require HTTPS for all remote transcription endpoints and reject plaintext HTTP URLs. 2. Allowlist trusted endpoint hosts, with `api.openai.com` as the default. If custom gateways are required, maintain an explicit administrator-controlled allowlist. 3. Parse and validate the URL before invoking `curl`. Reject malformed URLs, embedded usernames or passwords, unexpected schemes, and disallowed ports. 4. Do not automatically forward `OPENAI_API_KEY` to arbitrary OpenAI-compatible gateways. Support a separate gateway-specific credential, such as `OPENAI_PROXY_API_KEY`. 5. Require explicit user confirmation when a non-default endpoint will receive an audio file, and clearly display the destination host without revealing credentials. 6. Consider rejecting environment-based endpoint overrides in privileged or automated execution contexts unless they originate from a trusted configuration source. 7. Add tests confirming that HTTP URLs, embedded credentials, malformed URLs, and unapproved hosts are rejected. 8. Document the trust implications of custom gateways and advise users that both audio content and authentication credentials may be disclosed to the configured provider. A hardened implementation should validate the endpoint before constructing the request, for example by using a dedicated URL parser and comparing its protocol and hostname against an explicit policy. ]]>
