Back to skill

Security audit

elevenlabs

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent ElevenLabs helper that sends user-provided text or audio and an API key to ElevenLabs, with privacy/setup cautions but no evidence of hidden or destructive behavior.

Before installing, understand that generated-text prompts, dialogue inputs, music prompts, and voice-cloning audio files are sent to ElevenLabs using your API key. Store the API key carefully, avoid committing .env files, use only voice samples you have permission to upload, and delete local sample files when no longer needed.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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)

T08 · Insecure Dependencies

Warning
Location
SETUP.md:14
Finding

Unpinned Third-Party Dependency Installation

Content
View full analysis

Vulnerability Details

File Location: SETUP.md, lines 14–18
Vulnerability Type: Unpinned and unverified Python dependency
Risk Level: Medium

Vulnerable Code

markdown
Requires the `requests` Python package:

```bash
python3 -m pip install requests
text

### Technical Analysis

The setup instructions install `requests` without a version constraint, cryptographic hash verification, lockfile, or isolated virtual environment. Consequently, the installed package and its transitive dependencies are resolved dynamically from the active Python package index at installation time.

Although no evidence indicates that the legitimate `requests` package is malicious, this mutable dependency resolution weakens reproducibility and exposes users to supply-chain risks. A compromised package release, compromised package index, malicious index configuration, or unexpected future dependency change could introduce attacker-controlled code after the Skill itself has been reviewed.

Python package installation may execute build-backend or source-distribution code. Malicious package code could also execute later when the Skill imports `requests`.

### Attack Path

1. A user follows `SETUP.md` and runs `python3 -m pip install requests`.
2. Pip contacts the configured package index and resolves the latest compatible `requests` package and transitive dependencies.
3. An attacker has compromised a resolved release, dependency, package index, or local pip index configuration.
4. Pip downloads and installs the attacker-controlled artifact without checking a project-supplied expected hash.
5. Malicious code executes during package build or installation, or later when one of the Skill scripts imports the installed package.
6. The code runs with the privileges of the user executing pip or the Skill.

### Impact Assessment

Successful exploitation could provide arbitrary code execution with the installing user’s privileges.
...[truncated 415 chars]
Remediation
View remediation

Remediation Suggestions

  1. Pin requests and every transitive dependency to reviewed versions in a requirements or lock file.

  2. Generate and require cryptographic hashes, for example:

    text
    requests==<reviewed-version> --hash=sha256:<verified-hash>
    

    Install it using:

    bash
    python3 -m pip install --require-hashes -r requirements.txt
    
  3. Use a dependency-locking tool that records the complete dependency graph and hashes.

  4. Install dependencies in a dedicated virtual environment rather than the user or system Python environment.

  5. Explicitly use a trusted package index and prevent unintended fallback to additional indexes.

  6. Add automated dependency vulnerability and integrity scanning to the release process.

  7. Periodically update pinned versions through a controlled review and testing process.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (39)

Tainted flow: 'headers' from os.environ.get (line 107, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/dialogs.py (reported line 128)May include surrounding context.

python
data["seed"] = seed
    
    # Make request
    response = requests.post(url, headers=headers, json=data, timeout=300)
    
    if response.status_code != 200:
        detail = response.text

Tainted flow: 'headers' from os.environ.get (line 130, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/quota.py (reported line 92)May include surrounding context.

python
url = "https://api.elevenlabs.io/v1/user/subscription"
    headers = {"xi-api-key": api_key}
    
    response = requests.get(url, headers=headers)
    if response.status_code != 200:
        raise RuntimeError(f"API error {response.status_code}: {response.text}")

Tainted flow: 'headers' from os.environ.get (line 130, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/quota.py (reported line 138)May include surrounding context.

python
"aggregation_interval": aggregation_interval,
    }
    
    response = requests.get(url, headers=headers, params=params)
    if response.status_code != 200:
        raise RuntimeError(f"API error {response.status_code}: {response.text}")

Tainted flow: 'api_key' from os.environ.get (line 41, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/sfx.py (reported line 70)May include surrounding context.

python
print(f"   Looping: enabled")
    print(f"   Influence: {prompt_influence}")
    
    response = requests.post(
        API_URL,
        headers={
            "xi-api-key": api_key,

Tainted flow: 'headers' from os.environ.get (line 67, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/speech.py (reported line 85)May include surrounding context.

python
}
    }
    
    response = requests.post(url, headers=headers, json=data)
    
    if response.status_code != 200:
        detail = response.text

Tainted flow: 'headers' from os.environ.get (line 76, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/voiceclone.py (reported line 158)May include surrounding context.

python
mime_type = mime_types.get(suffix, "audio/mpeg")
            files_list.append(("files", (path.name, file_handles[i], mime_type)))
        
        response = requests.post(url, headers=headers, files=files_list)
        
    finally:
        for fh in file_handles:

Tainted flow: 'api_key' from os.environ.get (line 23, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/voices.py (reported line 29)May include surrounding context.

python
sys.exit(1)

    try:
        response = requests.get(API_URL, headers={"xi-api-key": api_key}, timeout=30)
        response.raise_for_status()
        data = response.json()

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description focuses on audio generation and voice/quota management via the ElevenLabs API, but the supplied code chunk does not interact with ElevenLabs or audio generation at all. Instead, it implements a security/helper utility for validating output file paths and constraining them to approved directories. This is a materially different primary purpose from the declared functionality, so it should be flagged as a mismatch. While such a utility could support an audio skill, this code chunk by itself is unrelated to the declared API capabilities.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

The description overstates the skill's scope. The code only calls the ElevenLabs /v1/text-to-dialogue endpoint to generate combined dialogue audio from multiple text/voice_id inputs. It does not implement sound effects generation, music generation, voice listing/creation/editing/deletion, or any quota/subscription checking endpoints. While related to audio generation with ElevenLabs, its actual primary purpose is narrower: multi-speaker dialogue synthesis. The code also includes metadata output and ffmpeg-based speaker splitting, but since it does not obtain timestamps/segments from the API, those fields remain empty in practice. There is no evidence of unrelated malicious behavior; the mismatch is mainly that the declared description is substantially broader than the implemented functionality.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The supplied code is narrowly focused on one capability: composing music through the ElevenLabs /v1/music endpoint and saving the output. It does not perform text-to-speech, sound effects generation, voice management, or quota/account checks. While music generation is part of the declared description, the description materially overstates the functionality of this code chunk. There are no suspicious undeclared behaviors beyond expected network access to ElevenLabs and local file output.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
90% confidence
Finding

The code is narrowly focused on calling ElevenLabs's text-to-speech endpoint (/v1/text-to-speech/{voice_id}), saving returned audio, and optionally printing a character cost value from the response headers. It does not include any endpoints or logic for sound effects generation, music generation, listing/creating/editing/deleting voices, or checking account quota/usage. While the declared description includes TTS, it materially overstates the skill's capabilities in several areas, so the description does not accurately represent the actual behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

The declared description presents this as a general ElevenLabs audio-generation and voice-management skill, including text-to-speech, sound effects, music generation, and quota checks. The supplied code does none of those broad functions. Instead, it is narrowly focused on instant voice cloning: it reads user-provided local audio files from a constrained directory, validates file type/size, and uploads them to ElevenLabs' voice creation endpoint. While voice cloning could loosely fall under 'voice management,' it is a distinct and significant capability not explicitly mentioned, and the declared primary purpose materially overstates other supported features that are absent from this code chunk. Therefore the description does not accurately represent the actual behavior.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The setup instructions explicitly recommend persisting the ElevenLabs API key in environment variables, shell profiles, and optional .env files, but provide no warning about credential sensitivity, file permissions, accidental source control commits, or shared-system exposure. While this is common documentation practice, it increases the likelihood of long-lived secret leakage through dotfiles, backups, logs, or repository check-ins.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · SETUP.md (reported line 62)May include surrounding context.

Copy your voice samples there before running voice clone commands:

bash
mkdir -p ~/.openclaw/elevenlabs/voiceclone-samples
cp ~/path/to/sample.mp3 ~/.openclaw/elevenlabs/voiceclone-samples/

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding

The skill advertises and documents capabilities that require shell execution, filesystem access, environment-variable access, and outbound network access, yet it declares no explicit tool scope such as permissions or allowed-tools. This creates an overbroad execution surface where an orchestrator may grant more authority than users expect, increasing the chance of unintended file access, command execution, or secret use.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

Voice cloning involves uploading potentially sensitive biometric voice samples to an external API, but the documentation does not warn about consent, privacy, retention, or third-party processing implications. Users may unknowingly submit another person's voice or confidential recordings, creating privacy, legal, and policy risk.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
67% confidence
Finding

The documented workflow relies on storing reusable voice-cloning samples under a persistent directory in the user's home folder. Persisting sensitive voice samples beyond immediate use increases exposure to local compromise, accidental reuse, or unauthorized access, especially because voice data is privacy-sensitive and can enable impersonation.

Content

Scanner excerpt · SKILL.md (reported line 122)May include surrounding context.

text

### 5. Voice Cloning (`voiceclone.py`)
Create instant voice clones from audio samples.

**Security:** by default this script will only read files from:
- `~/.openclaw/elevenlabs/voiceclone-samples/`

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The module docstring says it generates dialogue "with timestamps" and shows module usage returning result.voice_segments and result.alignment. However, generate_dialogue explicitly notes the endpoint returns raw audio only and returns voice_segments=[], alignment=None, and normalized_alignment=None, so the documentation actively misstates the behavior users can rely on.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The code sends the full inputs payload, which contains user dialogue text and voice identifiers, to an external HTTP endpoint via requests.post. While the module docstring describes the API wrapper, it does not explicitly warn users that their input content will be transmitted to a third-party service.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/dialogs.py (reported line 185)May include surrounding context.

python
str(clip_path),
        ]
        
        result = subprocess.run(cmd, capture_output=True, text=True)
        if result.returncode != 0:
            print(f"Warning: ffmpeg failed for segment {i}: {result.stderr}", file=sys.stderr)
            continue

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% 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/music.py (reported line 72)May include surrounding context.

python
else:
        raise ValueError("Either prompt or composition_plan_json must be provided")

    response = requests.post(url, headers=headers, params=params, json=payload, timeout=120)

    if response.status_code >= 400:
        detail = response.text.strip()

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% 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/sfx.py (reported line 70)May include surrounding context.

python
print(f"   Looping: enabled")
    print(f"   Influence: {prompt_influence}")
    
    response = requests.post(
        API_URL,
        headers={
            "xi-api-key": api_key,

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The manifest describes capabilities around ElevenLabs API usage for text-to-speech, sound effects, music generation, voice management, and quota checks. The --play option adds an extra local-execution capability by invoking afplay through subprocess.run, which is not part of generating or managing audio via the ElevenLabs API and expands the skill into local media execution.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/sfx.py (reported line 170)May include surrounding context.

python
if args.play:
            import subprocess
            print(f"🔊 Playing...")
            subprocess.run(["afplay", str(output_path)], check=True)
            
    except ValueError as e:
        print(f"❌ Validation error: {e}", file=sys.stderr)

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The module usage example at L009-L010 assigns the result of generate_speech to audio_bytes, and the function signature at L054 declares -> bytes, implying a single bytes return value. However, L095-L099 show the function returns (response.content, character_cost), which contradicts the documented and annotated behavior and could mislead callers about side effects and data returned.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.