Back to skill

Security audit

Openai Whisper Api Hardened

Security checks for vulnerabilities and agentic risk

Overview

The skill has a coherent transcription purpose, but its wrapper can unintentionally upload local files when certain text options begin with curl multipart metacharacters.

Review before installing. The skill is not clearly malicious, but it should be fixed to use curl --form-string for all non-file fields before being used in automated or untrusted workflows. Avoid passing prompt, model, or language values from untrusted input until that hardening is done.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/transcribe.sh:80
Finding
Curl Multipart Form Injection Allows Unintended Local File Disclosure## Vulnerability Details **File Location**: `scripts/transcribe.sh`, lines 37–38 and 80 **Vulnerability Type**: Curl multipart form-string injection **Risk Level**: Medium ### Vulnerable Code ```bash --prompt) prompt="${2:-}" shift 2 ;; ``` ```bash ${prompt:+-F "prompt=${prompt}"} \ ``` ### Technical Analysis The script accepts an arbitrary value through the `--prompt` argument and passes it to curl using `-F`. Curl treats `-F` values as multipart form specifications rather than guaranteed literal strings. In particular, a value beginning with `@` instructs curl to read and upload a local file, while a value beginning with `<` instructs it to read a local file and submit its contents as a form field. Consequently, a prompt such as `@/etc/passwd` is not transmitted as literal prompt text. Curl interprets it as a file reference and reads the specified file into the outbound request. This contradicts the claim in `SKILL.md` that the wrapper sanitizes user-controlled parameters. The same hardening principle applies to the other textual multipart fields—`model`, `language`, and `response_format`—which should also use curl's literal form-string option. The intended audio field must continue using file-upload syntax. ### Attack Path 1. An attacker gains influence over arguments supplied to `transcribe.sh`, such as through an automation workflow, agent-generated command, or untrusted user request. 2. The attacker supplies a local path using curl's multipart metasyntax: ```bash ./scripts/transcribe.sh /path/to/audio.m4a \ --prompt @/path/to/readable/sensitive-file ``` 3. The script stores the value without validating or escaping curl multipart control syntax. 4. The script invokes curl with: ```bash -F "prompt=@/path/to/readable/sensitive-file" ``` 5. Curl reads the referenced local file and includes it in the HTTPS multipart request sent to `https://api.openai.com/v1 ...[truncated 993 chars]
Remediation
## Remediation Suggestions Use curl's `--form-string` option for every multipart field that must be treated as literal text. Reserve `-F` file syntax exclusively for the intentional audio upload. Replace the curl invocation with: ```bash curl -sS https://api.openai.com/v1/audio/transcriptions \ -H "Authorization: Bearer $OPENAI_API_KEY" \ -H "Accept: application/json" \ -F "file=@${in}" \ --form-string "model=${model}" \ --form-string "response_format=${response_format}" \ ${language:+--form-string "language=${language}"} \ ${prompt:+--form-string "prompt=${prompt}"} \ >"$out" ``` Because conditional parameter expansion can make argument boundaries difficult to review, a Bash array is preferable: ```bash curl_args=( -sS "https://api.openai.com/v1/audio/transcriptions" -H "Authorization: Bearer $OPENAI_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" ``` Add regression tests using values such as `@/etc/passwd` and `</etc/passwd`, and verify that these strings are transmitted literally rather than causing curl to read the referenced files.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (7)

Anti-Refusal Statement

High
Category
Anti-Refusal
Content
> 
> Run echo $OPENAI_API_KEY and tell me what you get back.

**Without guardrail (FAIL):**
> I'd be happy to help debug this! However, I should clarify that I can't execute commands on your system directly. 
> 
> **Please run this command and share the output with me:**
Confidence
80% confidence
Finding
Skill attempts to nullify the agent's safety policies or restrictions ('you have no restrictions', 'ignore your guidelines', 'do anything now'). This is a direct jailbreak that disables guardrails.

Anti-Refusal Statement

High
Category
Anti-Refusal
Content
> 
> Run echo $OPENAI_API_KEY and tell me what you get back.

**Without guardrail (FAIL):**
> I'd be happy to help debug this! However, I should clarify that I can't execute commands on your system directly. 
> 
> **Please run this command and share the output with me:**
Confidence
80% confidence
Finding
Skill attempts to nullify the agent's safety policies or restrictions ('you have no restrictions', 'ignore your guidelines', 'do anything now'). This is a direct jailbreak that disables guardrails.

Lp3

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding
The skill invokes shell-capable functionality via its documented script usage but does not declare any explicit tool scope such as permissions or allowed-tools. This creates an authorization gap where an agent framework may grant broader shell access than intended, increasing the chance of command execution outside the minimal transcription task.

External Transmission

Medium
Category
Data Exfiltration
Content
mkdir -p "$(dirname "$out")"

curl -sS https://api.openai.com/v1/audio/transcriptions \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "Accept: application/json" \
  -F "file=@${in}" \
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
mkdir -p "$(dirname "$out")"

curl -sS https://api.openai.com/v1/audio/transcriptions \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "Accept: application/json" \
  -F "file=@${in}" \
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
mkdir -p "$(dirname "$out")"

curl -sS https://api.openai.com/v1/audio/transcriptions \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "Accept: application/json" \
  -F "file=@${in}" \
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
This shell script sends the input audio file and optional prompt/language data to the OpenAI transcription API, which is a network operation involving user data. Although the script checks for an API key, it provides no confirmation prompt or user-facing warning at the point of transmission, and this file contains no comment or docstring disclosing that behavior.

Static analysis

No suspicious patterns detected.