Back to skill

Security audit

OpenClaw TTS Voice Switch

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its stated TTS voice-switching purpose, but it handles ElevenLabs API keys in an unsafe command-line form and performs local config changes plus a gateway restart.

Review before installing. Expect the skill to read or modify ~/.openclaw/openclaw.json, query ElevenLabs for voice metadata, and restart the OpenClaw gateway. Do not use the documented fourth apiKey command-line argument; rely on an already protected config value or a safer secret-entry method, and rotate the key if it was placed in shell history.

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/switch_tts_voice.sh:4
Finding

ElevenLabs API Key Exposed Through Command-Line Arguments

Content
View full analysis

Vulnerability Details

File Location: scripts/switch_tts_voice.sh, lines 4-12
Related Documentation: SKILL.md, lines 47-50
Vulnerability Type: Sensitive credential exposure through command-line arguments
Risk Level: Medium

Vulnerable code:

bash
if [[ $# -lt 1 || $# -gt 4 ]]; then
  echo "usage: $0 <voiceId> [languageCode] [modelId] [apiKey]" >&2
  exit 1
fi

VOICE_ID="$1"
LANGUAGE_CODE="${2:-zh}"
MODEL_ID="${3:-eleven_multilingual_v2}"
API_KEY="${4:-}"

Documented invocation:

bash
bash scripts/switch_tts_voice.sh "<voiceId>"
bash scripts/switch_tts_voice.sh "<voiceId>" "<languageCode>"
bash scripts/switch_tts_voice.sh "<voiceId>" "<languageCode>" "<modelId>"
bash scripts/switch_tts_voice.sh "<voiceId>" "<languageCode>" "<modelId>" "<apiKey>"

Credential processing code (scripts/switch_tts_voice.sh, lines 24-36):

bash
jq --arg voiceId "$VOICE_ID" --arg languageCode "$LANGUAGE_CODE" --arg modelId "$MODEL_ID" --arg apiKey "$API_KEY" '
  .messages.tts as $existingTts |
  .messages.tts = {
    "auto": (($existingTts.auto // "always")),
    "provider": "elevenlabs",
    "elevenlabs": (
      ($existingTts.elevenlabs // {})
      + {
        "modelId": $modelId,
        "languageCode": $languageCode,
        "voiceId": $voiceId
      }
      + (if ($apiKey | length) > 0 then {"apiKey": $apiKey} else {} end)
    )
  }

Technical Analysis

The script accepts a long-lived ElevenLabs API key as its fourth positional argument, and the skill documentation explicitly instructs users to invoke it that way. Shell quoting prevents metacharacter interpretation but does not provide confidentiality.

Secrets supplied on a command line may be retained in shell history, terminal-session recordings, audit logs, support bundles, or command telemetry. They may also ...[truncated 1446 chars]

Remediation
View remediation

Remediation Suggestions

  1. Remove the API key from the positional-argument interface and usage text.
  2. Prefer the API key already stored in the protected OpenClaw configuration or obtain it from a dedicated secret manager.
  3. For interactive configuration, read the value without echoing:
    bash
    read -rs -p "ElevenLabs API key: " API_KEY
    printf '\n' >&2
    
  4. If standard input is used, clearly document that callers must not place the secret directly in the shell command.
  5. When environment-based injection is necessary, use a secret-management facility and ensure the environment is not captured by debugging or telemetry systems.
  6. Pass sensitive data to jq through a protected temporary input or inherited file descriptor rather than --arg, because --arg places the value in the child process's command-line arguments.
  7. Update SKILL.md so no example demonstrates passing credentials on a command line.
  8. Advise existing users who followed the documented command to remove affected history entries and rotate the exposed API key.
  9. Ensure ~/.openclaw/openclaw.json and backups containing credentials have restrictive permissions, such as mode 0600.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • 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
Findings (9)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The documented behavior does not match the detected operational behavior: the skill appears to call an external API, read credentials, and omit some claimed local changes and restart actions. This mismatch is dangerous because reviewers and users may authorize the skill for a benign local config change while it actually accesses secrets and external services, creating hidden data exposure and trust-boundary violations.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill invokes shell-based workflows but does not declare any explicit tool scope or permissions boundary. This is dangerous because an agent or user may execute file-modifying or service-affecting commands without clear upfront authorization, reducing reviewability and increasing the chance of unintended command execution.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The workflow instructs modification of a user configuration file and suggests a gateway restart, but does not present this as an explicit warning requiring user awareness. That is risky because configuration changes and service restarts can disrupt availability, overwrite existing settings, or cause the user to approve actions without understanding their side effects.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The file states it keeps messages.tts.elevenlabs.languageCode = "zh" unless the user explicitly wants something else, which imposes a specific language by default. The policy requires user choice or clearly justified locale constraints, and this file does not present the Chinese default as an opt-in or region-specific compliance requirement.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This shell script reads an ElevenLabs API key from a local config file or environment variables and then sends it in a curl request header to an external service. The script contains no user-facing notice, confirmation, or explanatory comment about credential use or the outbound network call, which matches the missing-warning criterion for code files.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The manifest describes a narrowly scoped local operation: updating ~/.openclaw/openclaw.json to switch voices and restarting the gateway. This script instead supports credential discovery from environment variables and performs a network request to enumerate remote ElevenLabs voices, which is a distinct capability not implied by the stated purpose.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/list_voices.sh (reported line 26)May include surrounding context.

sh
exit 1
fi

raw="$(curl -sS https://api.elevenlabs.io/v1/voices -H "xi-api-key: $api_key")"

if [[ -z "$LANGUAGE_FILTER" ]]; then
  jq -r '

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script silently sets LANGUAGE_CODE to zh when the user does not provide a language, forcing a specific locale choice. This is a natural-language policy concern because the user is not offered a language choice or asked to opt into that default.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This code overwrites ~/.openclaw/openclaw.json and then runs openclaw gateway restart, which changes local configuration and affects service state. While it prints status after the fact, there is no pre-action warning, confirmation prompt, or comment/docstring disclosing these safety-relevant side effects.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.