Back to skill

Security audit

K8s Self Hosted Whisper Api

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent Whisper transcription helper, but it sends sensitive audio over unauthenticated HTTP and has a prompt-handling bug that can allow local command execution.

Review before installing. Use only in a trusted internal environment, avoid sensitive recordings unless you accept the unauthenticated HTTP upload risk, and do not pass untrusted text to --prompt until the script is fixed to URL-encode arguments safely without building executable Python source.

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 (2)

T09 · Insecure Skill Coding Practices

Error
Location
transcribe.sh:87
Finding
Arbitrary Python Code Execution Through the Prompt Argument<![CDATA[ ## Vulnerability Details **File Location**: `transcribe.sh:87` **Vulnerability Type**: Python source-code injection **Risk Level**: High ### Vulnerable Code ```bash [[ -n "$PROMPT" ]] && QUERY="${QUERY}&initial_prompt=$(python3 -c "import urllib.parse; print(urllib.parse.quote('${PROMPT}'))" 2>/dev/null || echo "${PROMPT}")" ``` ### Technical Analysis The user-controlled `PROMPT` value is interpolated directly into Python source passed to `python3 -c`. The shell's quoting protects the value from direct shell interpretation, but it does not make the resulting Python source safe. Quotes and Python syntax contained in the expanded value are parsed by the Python interpreter. An attacker can supply a prompt that closes the Python string and injects additional Python statements. For example, a value following this pattern can invoke operating-system commands: ```text '); __import__("os").system("id"); # ``` The constructed Python program would contain attacker-controlled executable syntax. Suppressing Python's standard error output does not prevent exploitation and may make failed or attempted exploitation less visible. The fallback `echo "${PROMPT}"` is also not a safe URL-encoding mechanism, although it does not independently produce code execution because the value remains quoted there. ### Attack Path 1. An attacker supplies or convinces an agent to use a malicious value for `--prompt`. 2. The argument parser stores that value in `PROMPT`. 3. Line 87 inserts it directly between Python string delimiters in the `python3 -c` source. 4. The malicious value terminates the intended string and appends Python statements. 5. `python3` executes those statements with the privileges and environment of the user running the Skill. 6. The injected code can invoke local commands, read accessible files, modify data, or initiate additional network requests. ### Impact Assessment Successful exploitation provides arbitrary local code execution under the accoun ...[truncated 355 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Never interpolate untrusted data into executable source. Pass the prompt as a separate positional argument: ```bash ENCODED_PROMPT=$( python3 -c \ 'import sys, urllib.parse; print(urllib.parse.quote(sys.argv[1], safe=""))' \ "$PROMPT" ) QUERY="${QUERY}&initial_prompt=${ENCODED_PROMPT}" ``` A stronger design is to avoid manually assembling the query string and let `curl` perform URL encoding: ```bash curl \ --silent \ --show-error \ --fail \ --request POST \ --form "audio_file=@${INPUT_FILE}" \ --get \ --data-urlencode "task=${TASK}" \ --data-urlencode "output=${OUTPUT_FORMAT}" \ --data-urlencode "initial_prompt=${PROMPT}" \ "${BASE_URL}/asr" ``` Adapt the request construction as necessary to preserve the required POST and multipart semantics. In addition: - Validate `TASK` and `OUTPUT_FORMAT` against strict allowlists. - Validate language codes against the formats accepted by the service. - Add automated tests containing quotes, semicolons, newlines, Python syntax, and shell metacharacters. - Do not silently fall back to an unencoded prompt if encoding fails; terminate with an explicit error instead. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
transcribe.sh:96
Finding
Sensitive Audio and Prompt Data Transmitted Over Unauthenticated Plaintext HTTP<![CDATA[ ## Vulnerability Details **File Location**: `transcribe.sh:6, 96-103`; `SKILL.md:12, 46-48` **Vulnerability Type**: Cleartext transmission of potentially sensitive information **Risk Level**: Medium ### Vulnerable Code ```bash BASE_URL="http://whisper-asr.whisper-asr.svc.cluster.local:9000" ``` ```bash RESPONSE=$(curl \ --silent \ --show-error \ --fail \ --request POST \ --header "content-type: multipart/form-data" \ --form "audio_file=@${INPUT_FILE}" \ "${BASE_URL}/asr?${QUERY}") ``` The documentation explicitly confirms the transport and authentication design: ```markdown Transcribe an audio file via the Whisper ASR webservice at `http://whisper-asr.whisper-asr.svc.cluster.local:9000`. ``` ```markdown - Swagger docs available at `http://whisper-asr.whisper-asr.svc.cluster.local:9000/docs` - No authentication required ``` ### Technical Analysis The script uploads the complete audio file and places request parameters, including the optional initial prompt, in a URL query string over plaintext HTTP. No TLS certificate verification, client identity, authorization token, or other service-authentication mechanism is used. The internal Kubernetes DNS name reduces exposure compared with a public Internet endpoint, but it does not provide confidentiality or cryptographic service identity. A compromised pod, node, network component, sidecar, or internal service with suitable network visibility may observe the recording and prompt. DNS or traffic-routing compromise may also redirect the request to an impersonated service, which can collect uploaded files or return manipulated transcripts. Query parameters may additionally appear in proxy, ingress, service, or application access logs, increasing the exposure of prompt content. ### Attack Path 1. A user invokes the Skill with a potentially sensitive recording and, optionally, a contextual prompt. 2. The script resolves the internal service name and sends a plaintext multipart HTTP requ ...[truncated 976 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Protect the service with authenticated TLS: - Expose the ASR service through HTTPS using a certificate trusted by the client. - Keep `curl` certificate verification enabled; do not use `--insecure`. - Use workload identity, mutual TLS, or a short-lived service token to authenticate requests. - Authorize only the workloads and service accounts that require transcription access. - Apply Kubernetes NetworkPolicies that restrict ingress to the ASR service and egress from the Skill workload. - Prefer a service mesh with enforced mTLS if one is available. - Avoid putting sensitive prompt content in the URL. Send it in an appropriately protected request body when supported. - Configure proxies and the ASR service not to log sensitive query parameters or uploaded content. - Document that audio leaves the local process and is sent to the internal ASR service. - Define retention, access-control, and deletion policies for uploaded audio and generated transcripts. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (4)

Lp3

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding
The skill exposes shell and network-capable behavior but does not declare any explicit tool scope or permission boundaries. That makes it easier for an agent framework to invoke the skill without clear governance, increasing the chance of unintended network access and command execution around user-supplied file paths.

Vague Triggers

Medium
Confidence
92% confidence
Finding
The trigger language is broad enough that the skill may activate for many general transcription or translation requests without clearly signaling that user audio will be sent to an internal HTTP service. Over-broad activation increases the risk of unintended data disclosure, especially for sensitive voice recordings or subtitles derived from them.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The skill sends user audio over plain HTTP to a network service and does not warn the user that their content leaves the local execution context. Audio often contains sensitive personal or business information, so undisclosed transmission over an unencrypted channel creates confidentiality and privacy risk, especially in shared or multi-tenant environments.

Natural-Language Policy Violations

Low
Confidence
78% confidence
Finding
The note states that `--translate` produces an English transcript regardless of source language. This imposes a specific language outcome without documenting user choice or opt-in, which can violate language or locale preference expectations.

Static analysis

No suspicious patterns detected.