Back to skill

Security audit

Pronunciation Coach

Security checks for vulnerabilities and agentic risk

Overview

This pronunciation-coaching skill mostly does what it says, but it uploads voice data to Azure and has avoidable handling risks for speech content and the Azure API key.

Install only if you are comfortable sending selected voice recordings and reference text to Microsoft Azure Speech Services. Use a restricted Azure Speech key, avoid passing the key as a command-line argument, rotate it if used on shared systems, and avoid running the report in terminals or CI logs that other people can read.

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/pronunciation-assess.sh:8
Finding
Azure Speech API Key Exposed in Process Command-Line Arguments## Vulnerability Details **File Location**: `scripts/pronunciation-assess.sh`, lines 8-10 and 65-69 **Vulnerability Type**: Sensitive credential exposure through process arguments **Risk Level**: Medium ### Vulnerable Code ```bash AZURE_KEY="${3:-$AZURE_SPEECH_KEY}" AZURE_REGION="${4:-$AZURE_SPEECH_REGION}" ``` ```bash RESULT=$(curl -s -X POST \ "${ENDPOINT}?language=en-US&format=detailed" \ -H "Ocp-Apim-Subscription-Key: ${AZURE_KEY}" \ -H "Content-Type: ${CONTENT_TYPE}" \ -H "Pronunciation-Assessment: ${PRON_CONFIG}" \ ``` ### Technical Analysis The script accepts an Azure Speech API key as positional argument 3 and expands the key directly into a `curl` header argument. The expanded header, including the secret, can therefore be present in the command-line metadata of the running `curl` process. Supplying the key through `AZURE_SPEECH_KEY` instead of argument 3 does not fully mitigate the issue. In either case, the shell expands `${AZURE_KEY}` before starting `curl`, causing the resulting header value to be included in `curl`'s process arguments. Depending on the operating system's process-inspection restrictions, local users, processes running under the same account, monitoring agents, diagnostic utilities, or a compromised local process may be able to inspect this metadata. The exposure exists for the duration of each Azure request. ### Attack Path 1. An authorized user invokes `pronunciation-assess.sh` with a valid Azure Speech API key, either through argument 3 or the `AZURE_SPEECH_KEY` environment variable. 2. The script starts `curl` and places `Ocp-Apim-Subscription-Key: <secret>` in its argument vector. 3. While the request is active, a local process with permission to inspect the target process reads its command-line metadata, such as through process-monitoring facilities. 4. The inspecting process extracts the Azure subscription key from the header argument. 5. The ...[truncated 689 chars]
Remediation
## Remediation Suggestions 1. Remove support for passing the Azure key as a positional command-line argument. 2. Avoid expanding the credential into a `curl` command-line header argument. 3. Supply the sensitive header through a protected curl configuration file or another mechanism that does not expose the value in process arguments. 4. If a temporary configuration file is used: - Create it with `mktemp`. - Set permissions to `0600` before writing the credential. - Store it only in a trusted local directory. - Register an `EXIT`, `INT`, `TERM`, and `HUP` trap to remove it reliably. - Do not print its contents or include the key in error messages. 5. Restrict the Azure key to the minimum required service and resource scope where supported. 6. Rotate the existing key if the script has been used on systems where untrusted processes could inspect command-line metadata. 7. Prefer short-lived Azure authentication credentials where the deployment environment supports them.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (7)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The documented behavior claims real audio analysis with Azure Speech Services, while the analyzed implementation appears to only post-process JSON and not perform the described audio handling itself. This mismatch can mislead operators about what data is accessed, what external services are contacted, and what security/privacy controls are actually in effect, which undermines trust and reviewability.

Lp3

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding
The skill instructs use of shell commands and local file access but does not declare any explicit tool scope or permissions. That creates an authorization and transparency gap: an agent may be induced to access local audio files and invoke scripts without clear least-privilege boundaries or user-visible approval.

External Transmission

Medium
Category
Data Exfiltration
Content
}" | base64 | tr -d '\n')

# API call using --data-binary to point to the temporary file
RESULT=$(curl -s -X POST \
    "${ENDPOINT}?language=en-US&format=detailed" \
    -H "Ocp-Apim-Subscription-Key: ${AZURE_KEY}" \
    -H "Content-Type: ${CONTENT_TYPE}" \
Confidence
70% 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
The script sends the converted audio file and pronunciation assessment metadata derived from the user-provided reference text to a remote Azure Speech endpoint. While the code is commented and its purpose is evident, there is no explicit user-facing disclosure at execution time about transmitting potentially sensitive voice data off-host.

Natural-Language Policy Violations

Medium
Confidence
90% confidence
Finding
The request appends `language=en-US` unconditionally, which forces a specific language/locale regardless of the user's preferences or input. This is a natural-language policy concern because the file provides no opt-in, configurability, or justification for the locale constraint.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The script prints recognized speech content directly to stdout, including `best.Display`, word-level breakdowns, and phoneme details. Speech transcripts can contain sensitive personal or business information, and emitting them without masking, minimization, or a privacy warning can expose data in terminals, logs, CI output, or other downstream collectors.

Missing User Warnings

Medium
Confidence
98% confidence
Finding
On parse failure, the error handler prints the first 500 characters of raw input, which may include full or partial speech-recognition results and any embedded metadata. This creates an unnecessary disclosure path because malformed input often ends up in logs during troubleshooting, increasing the chance that sensitive user content is retained or exposed.

Static analysis

No suspicious patterns detected.