Back to skill

Security audit

Speak Turbo - Talk to your Claude 90ms latency!

Security checks for vulnerabilities and agentic risk

Overview

Speak-Turbo is a coherent local text-to-speech skill, but it needs review because it installs unpinned code and runs a localhost TTS daemon without authentication or resource limits.

Review before installing, especially on shared or sensitive machines. Prefer running it in an isolated environment, avoid speaking sensitive text aloud, stop the daemon when finished, do not permanently allow broad output directories, and pin or verify dependencies before using the installer.

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

T09 · Insecure Skill Coding Practices

Warning
Location
speakturbo/daemon_streaming.py:71
Finding

Unauthenticated Local TTS Endpoint Permits Cross-Site Resource Exhaustion

Content
View full analysis
Remediation
View remediation
`, on every endpoint. 4. Change `/tts` from GET to POST and accept text through a request body. 5. Reject browser-originated requests unless their `Origin` is explicitly trusted. Do not rely solely on CORS response headers as authentication. 6. Impose a strict maximum text length appropriate for the intended TTS workload. 7. Add per-client rate limiting and a small global limit on concurrent generations. 8. Apply request and generation timeouts, and cancel model generation when the client disconnects. 9. Continue binding only to `127.0.0.1`, while retaining Host validation as defense in depth. 10. Add tests demonstrating that missing or incorrect tokens, untrusted origins, oversized text, and excessive concurrent requests are rejected. ]]>

T08 · Insecure Dependencies

Warning
Location
install.sh:11
Finding

Installation Executes Broadly Versioned Third-Party Dependencies Without Reproducible Locks

Content
View full analysis
=0.1.0,<1.0" "uvicorn>=0.20.0,<1.0" "fastapi>=0.100.0,<1.0" "python-dateutil>=2.7,<3.0" ``` `install.sh:20-24`: ```bash if command -v cargo &> /dev/null && [ -d "$SCRIPT_DIR/speakturbo-cli" ]; then echo "→ Building Rust CLI from local source..." cd "$SCRIPT_DIR/speakturbo-cli" cargo build --release --quiet cp target/release/speakturbo ~/.local/bin/ ``` `pyproject.toml:24-28`: ```toml dependencies = [ "pocket-tts>=0.1.0", "fastapi>=0.100.0", "uvicorn>=0.20.0", "python-dateutil>=2.7", # Required by matplotlib (pocket-tts dependency) ] ``` `speakturbo-cli/Cargo.toml:6-11`: ```toml [dependencies] clap = { version = "4", features = ["derive"] } ureq = "2" rodio = { version = "0.17", default-features = false, features = ["wav"] } anyhow = "1" dirs = "5" ``` `README.md:31-39`: ```bash # For AI agents npx skills add EmZod/Speak-Turbo # CLI only pip install pocket-tts uvicorn fastapi cd speakturbo-cli && cargo build --release ``` `.github/workflows/install-test.yml:8-12`: ```yaml steps: - name: Install skills run: | npx -y skills add EmZod/speak -y || true npx -y skills add EmZod/Speak-Turbo -y || true ``` ### Technical Analysis The installer resolves and executes the latest dependency versions matching broad ranges. The repository structure provided for the audit does not include a `Cargo.lock` file or a hash-locked Python requirements file ...[truncated 2439 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Rogue AgentSelf-Modification, Session Persistence
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (23)

Possible Typosquatting: 'uvicorn' resembles popular package 'gunicorn'

High
Category
Supply Chain
Confidence
70% confidence
Finding

Package name closely resembles a popular package, suggesting possible typosquatting. Attackers publish malicious packages with similar names to trick developers into installing them.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
92% confidence
Finding

The README instructs users to install the skill via npx skills add EmZod/Speak-Turbo without pinning a specific immutable version, commit, or digest. This creates a supply-chain risk: a future compromised or malicious update to the referenced package/repository could be pulled and executed by users or agents at install time.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill documentation describes capabilities involving shell commands, local file reads/writes, and network access, but the skill declares no explicit tool scope or permissions boundary. In an agent setting, this can cause the agent to invoke higher-risk operations than a user expects, increasing the chance of unintended file modification, process management, or local service interaction.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
90% confidence
Finding

The skill documents persistent modification of ~/.speakturbo/config to permanently expand allowed output directories. This creates session persistence beyond the immediate task and weakens future path restrictions, so a one-time agent action can broaden write access for later runs without renewed user intent.

Content

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

  • Your current working directory
  • ~/.speakturbo/

If you need to write elsewhere, use --allow-dir:

bash
speakturbo "Hello" -o /custom/path/audio.wav --allow-dir /custom/path

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 · install.sh (reported line 16)May include surrounding context.

sh
echo "→ Installing Python dependencies..."
pip install --quiet "pocket-tts>=0.1.0,<1.0" "uvicorn>=0.20.0,<1.0" "fastapi>=0.100.0,<1.0" "python-dateutil>=2.7,<3.0"

# Create bin directory
mkdir -p ~/.local/bin

# Build Rust CLI from local source, or fall back to Python wrapper

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 · speakturbo-cli/src/main.rs (reported line 181)May include surrounding context.

rust
);
    eprintln!("To allow it permanently, add to ~/.speakturbo/config:");
    eprintln!(
        "  mkdir -p ~/.speakturbo && echo \"{}\" >> ~/.speakturbo/config",
        parent_dir.display()
    );

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The CLI sends user-provided text to a local daemon over plain HTTP on 127.0.0.1 without any explicit disclosure at the point of use. Although loopback traffic is not exposed to the network in the usual case, sensitive text entered by the user is still being transmitted to another process, which may have different trust boundaries, logging behavior, or local interception risks on a compromised host.

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 · speakturbo/cli.py (reported line 61)May include surrounding context.

python
# Start streaming daemon as subprocess
    daemon_script = Path(__file__).parent / "daemon_streaming.py"
    
    # Create log directory
    log_dir = Path("/tmp")
    log_file = log_dir / "speakturbo.log"

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 · speakturbo/cli.py (reported line 66)May include surrounding context.

python
log_file = log_dir / "speakturbo.log"
    
    with open(log_file, "a") as log:
        process = subprocess.Popen(
            [sys.executable, str(daemon_script)],
            stdout=log,
            stderr=log,

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 · speakturbo/cli.py (reported line 175)May include surrounding context.

python
f"  speakturbo \"text\" -o {output} --allow-dir {parent_dir}\n"
        f"\n"
        f"To allow it permanently, add to ~/.speakturbo/config:\n"
        f"  mkdir -p ~/.speakturbo && echo \"{parent_dir}\" >> ~/.speakturbo/config",
        file=sys.stderr,
    )
    sys.exit(1)

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 · speakturbo/cli.py (reported line 242)May include surrounding context.

python
try:
            # Use afplay on macOS
            subprocess.run(["afplay", temp_path], check=True)
        except FileNotFoundError:
            # Try aplay on Linux
            try:

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 · speakturbo/cli.py (reported line 246)May include surrounding context.

python
except FileNotFoundError:
            # Try aplay on Linux
            try:
                subprocess.run(["aplay", temp_path], check=True)
            except FileNotFoundError:
                print(f"Audio saved to: {temp_path}", file=sys.stderr)
                print("Install afplay (macOS) or aplay (Linux) to play audio.", file=sys.stderr)

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 · speakturbo/tests/test_cli.py (reported line 23)May include surrounding context.

python
def run_cli(*args, input_text=None, timeout=30):
    """Run the CLI with given arguments."""
    cmd = ["python", CLI_PATH] + list(args)
    result = subprocess.run(
        cmd,
        capture_output=True,
        text=True,

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 · speakturbo/tests/test_cli.py (reported line 199)May include surrounding context.

python
"""Error message should show how to permanently allow via config."""
        result = run_cli("test", "-o", "/usr/share/speakturbo_test.wav")
        assert "~/.speakturbo/config" in result.stderr
        assert "mkdir -p" in result.stderr

    def test_allow_dir_flag_overrides_block(self):
        """--allow-dir should let you write to an otherwise-blocked path."""

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The skill prominently instructs immediate playback and describes daemon auto-start, but does not clearly warn that using it may produce audible speaker output or launch a background process. In shared or sensitive environments, this can leak information aloud, surprise users, or leave an unexpected resident process running.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The examples show using -o to write audio files but do not explicitly warn that the target file may be created or overwritten. This can lead to accidental data loss or unintended artifact creation if an agent selects an existing path or a sensitive working directory.

Content

No source excerpt is available for this finding.

Unverifiable Dependency: setuptools has 10 known advisory(ies) (CVE-2013-1633 (Setuptools vulnerable to Man-in-the-middle attacks); CVE-2025-47273 (setuptools has a path traversal vulnerability in PackageIndex.download that lead); CVE-2024-6345 (setuptools vulnerable to Command Injection via package URL) +7 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Content

No source excerpt is available for this finding.

Unverifiable Dependency: fastapi has 3 known advisory(ies) (CVE-2021-32677 (Cross-Site Request Forgery (CSRF) in FastAPI); CVE-2021-32677 (FastAPI is a web framework for building APIs with Python 3.6+ based on standard ); CVE-2024-24762 (FastAPI is a web framework for building APIs with Python 3.8+ based on standard )), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Content

No source excerpt is available for this finding.

Unverifiable Dependency: uvicorn has 4 known advisory(ies) (CVE-2020-7694 (Log injection in uvicorn); CVE-2020-7695 (HTTP response splitting in uvicorn); CVE-2020-7694 (This affects all versions of package uvicorn. The request logger provided by the) +1 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Content

No source excerpt is available for this finding.

Unverifiable Dependency: pytest has 2 known advisory(ies) (CVE-2025-71176 (pytest has vulnerable tmpdir handling); CVE-2025-71176 (pytest has vulnerable tmpdir handling)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
76% confidence
Finding

This code file exposes a network endpoint that accepts user text and processes it into audio, but the endpoint contains no confirmation prompt and no user-facing log, print, or inline warning about that processing. For code files, SQP-2 applies when data-processing or networked operations lack any visible disclosure, and the only docstring present is a terse implementation description rather than a user warning.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.