Back to skill

Security audit

speechfy

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent text-to-speech skill that sends provided text to documented TTS providers and writes audio output, with some privacy and hardening considerations but no evidence of hidden or malicious behavior.

Install only if you are comfortable sending TTS text to Speechify and, on fallback, Microsoft Edge TTS. Avoid using it for secrets or regulated data, use trusted paths for helper commands, prefer an isolated Python environment with pinned dependencies, and avoid shared predictable output paths under /tmp when possible.

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
scripts/speechfy-tts.py:89
Finding

Predictable Temporary Files Allow Local File Clobbering

Content
View full analysis
Remediation
View remediation

T08 · Insecure Dependencies

Note
Location
README.md:11
Finding

Unpinned Third-Party Dependency Installation

Content
View full analysis
Remediation
View remediation
" ``` 2. Maintain a lock file or requirements file containing cryptographic hashes and install it with hash enforcement: ```bash python3 -m pip install --require-hashes -r requirements.txt ``` 3. Install the dependency inside a dedicated virtual environment rather than into the system Python environment. 4. Do not install the package using root or administrator privileges. 5. Document the expected official package index and project identity. 6. Review and deliberately update the pinned version when security or compatibility updates are needed. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Output HandlingUnvalidated Output Injection, Cross-Context Output, Unbounded Output
Findings (27)

Tainted flow: 'req' from os.environ.get (line 69, credential/environment) → urllib.request.urlopen (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/speechfy-tts.py (reported line 80)May include surrounding context.

python
)

    try:
        resp = urllib.request.urlopen(req, timeout=30)
        data = json.loads(resp.read())
        audio_b64 = data.get("audio_data", "")
        if not audio_b64:

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · .env.example (reported line 2)May include surrounding context.

text
# Speechify TTS — Credentials
# Copy this to .env and fill in your values.
# .env is gitignored — never commit real credentials.

# Speechify API key (required for primary TTS)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · .env.example (reported line 3)May include surrounding context.

text
# Speechify TTS — Credentials
# Copy this to .env and fill in your values.
# .env is gitignored — never commit real credentials.

# Speechify API key (required for primary TTS)

Unvalidated Output Injection

High
Category
Output Handling
Confidence
85% confidence
Finding

Model output is used without validation or sanitization. Unvalidated output injected into downstream contexts (SQL, shell, HTML) enables injection attacks and arbitrary code execution.

Content

Scanner excerpt · README.md (reported line 127)May include surrounding context.

md
import subprocess

def generate_speech(text, output="/tmp/speech.ogg"):
    proc = subprocess.run(
        ["python3", "scripts/speechfy-tts.py", text, output],
        capture_output=True, text=True, timeout=60
    )

Unvalidated Output Injection

High
Category
Output Handling
Confidence
85% confidence
Finding

Model output is used without validation or sanitization. Unvalidated output injected into downstream contexts (SQL, shell, HTML) enables injection attacks and arbitrary code execution.

Content

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

md
import subprocess

def generate_speech(text, output="/tmp/speech.ogg"):
    proc = subprocess.run(
        ["python3", "scripts/speechfy-tts.py", text, output],
        capture_output=True, text=True, timeout=60
    )

Unvalidated Output Injection

High
Category
Output Handling
Confidence
85% confidence
Finding

Model output is used without validation or sanitization. Unvalidated output injected into downstream contexts (SQL, shell, HTML) enables injection attacks and arbitrary code execution.

Content

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

python
import subprocess
output = "/tmp/response.ogg"
subprocess.run([
    "python3", "scripts/speechfy-tts.py",
    text, output
], check=True)

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · docs/diagrama.svg (reported line 31)May include surrounding context.

text
<rect width="800" height="520" fill="url(#bg)" rx="12"/>
  <text x="400" y="38" text-anchor="middle" font-size="22" font-weight="bold" fill="#2d3436">Speechify TTS — Fluxo de Operação</text>

  <!-- Input -->
  <rect x="300" y="60" width="200" height="50" rx="10" fill="#636e72" filter="url(#shadow)"/>
  <text x="400" y="82" text-anchor="middle" font-size="14" font-weight="bold" fill="#fff">📝 Texto (CLI / SSML)</text>
  <text x="400" y="100" text-anchor="middle" font-size="10" fill="#dfe6e9">Argumento da linha de comando</text>

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · README.md (reported line 12)May include surrounding context.

bash
# 1. Install dependencies
pip install edge-tts       # for fallback (optional)
sudo apt install ffmpeg    # for audio conversion

# 2. Set your API key
export SPEECHIFY_API_KEY="sk_..."

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

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

bash
# 1. Install dependencies
pip install edge-tts       # for fallback (optional)
sudo apt install ffmpeg    # for audio conversion

# 2. Set your API key
export SPEECHIFY_API_KEY="sk_..."

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

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

bash
# 1. Install dependencies
pip install edge-tts       # for fallback (optional)
sudo apt install ffmpeg    # for audio conversion

# 2. Set your API key
export SPEECHIFY_API_KEY="sk_..."

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The README explicitly documents automatic fallback to Edge TTS but does not warn that the input text will be transmitted to a different third-party provider when Speechify fails. In a TTS skill, text may contain sensitive prompts, personal data, or secrets, so silent provider failover changes the data-processing boundary and creates a real privacy and compliance risk.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill clearly describes capabilities that require shell execution, environment-variable access, and outbound network access to external TTS providers, but it does not declare an explicit tool/permission scope. This can cause users or orchestration systems to invoke the skill without understanding its operational privileges, increasing the risk of unintended data egress and command execution.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill sends user-supplied text to third-party TTS services over the network, but the description does not prominently warn that content may leave the local environment. If users submit sensitive messages, credentials, or personal data, this omission can lead to unintended disclosure to external providers.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The SVG includes natural-language content specifying the fallback voice as "FranciscaNeural (pt-BR)", which indicates a fixed locale selection. Under the policy, forcing a specific language or locale without offering user choice or documenting a justified region-specific constraint is a violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The reference specifies only Portuguese voice options, including pt-BR fallback voices and a PT-PT section, but does not mention user opt-in, alternative locales, or a justification for restricting output to Portuguese variants. This can violate the language/locale policy because it implicitly enforces a locale choice without documenting consent or necessity.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
79% confidence
Finding

The manifest describes a multi-provider text-to-speech generator, but this code also attempts to locate and execute a separate vault-resolver program to retrieve credentials. Secret-resolution via an external executable is not mentioned in the stated purpose and goes beyond the obvious core function of generating speech audio.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
91% confidence
Finding

The script executes a helper binary whose path is taken from the VAULT_RESOLVER environment variable, with only a minimal os.path.isfile check. In environments where attackers can influence environment variables or working configuration, this can lead to execution of an arbitrary local program under the agent's privileges and exposure of requested secret material.

Content

Scanner excerpt · scripts/speechfy-tts.py (reported line 42)May include surrounding context.

python
vault_resolver = os.environ.get("VAULT_RESOLVER", "vault-resolver")
    if os.path.isfile(vault_resolver):
        try:
            proc = subprocess.run(
                [vault_resolver, "resolve"],
                input=json.dumps({"ids": [VAULT_ITEM]}).encode(),
                capture_output=True, timeout=20

Tainted flow: 'vault_resolver' from os.environ.get (line 39, credential/environment) → subprocess.run (code execution)

Medium
Category
Data Flow
Confidence
96% confidence
Finding

This is a real unsafe tainted flow because an environment-controlled executable path is launched directly. In agent or automation contexts, environment variables are often easier to influence than code, so this creates a realistic arbitrary program execution vector and could be abused to steal secrets or run unintended code.

Content

Scanner excerpt · scripts/speechfy-tts.py (reported line 42)May include surrounding context.

python
vault_resolver = os.environ.get("VAULT_RESOLVER", "vault-resolver")
    if os.path.isfile(vault_resolver):
        try:
            proc = subprocess.run(
                [vault_resolver, "resolve"],
                input=json.dumps({"ids": [VAULT_ITEM]}).encode(),
                capture_output=True, timeout=20

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The script sends arbitrary input text to external TTS providers without any explicit warning, confirmation, or filtering. In an agent setting, users may provide sensitive prompts, credentials, or personal data, so silent third-party transmission can create meaningful privacy and compliance exposure.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
89% confidence
Finding

This skill performs external transmission of user-provided text and an authorization credential to a third-party API. In the context of an agent skill, that is security-relevant because users may not expect their content to leave the local environment, and sensitive text could be disclosed to a vendor service.

Content

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

python
}

    req = urllib.request.Request(
        "https://api.speechify.ai/v1/audio/speech",
        data=json.dumps(payload).encode(),
        headers={
            "Authorization": f"Bearer {key}",

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/speechfy-tts.py (reported line 92)May include surrounding context.

python
mp3_tmp = output_path + ".tmp.mp3"
        with open(mp3_tmp, "wb") as f:
            f.write(base64.b64decode(audio_b64))
        subprocess.run(
            ["ffmpeg", "-y", "-i", mp3_tmp,
             "-c:a", "libopus", "-b:a", "32k",
             output_path],

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
73% confidence
Finding

Although audio generation is aligned with the skill purpose, the implementation achieves it by executing local programs for media conversion and fallback synthesis. The manifest description mentions providers and output format, but not that the skill executes host-installed binaries, which is a materially broader capability than a pure API-backed TTS skill.

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/speechfy-tts.py (reported line 134)May include surrounding context.

python
edge_cmd = resolve_edge_cmd()
    tmp = output_path + ".edge.mp3"
    try:
        subprocess.run(
            [edge_cmd, "--voice", EDGE_VOICE,
             "--text", text,
             "--write-media", tmp],

Tainted flow: 'EDGE_VOICE' from os.environ.get (line 25, credential/environment) → subprocess.run (code execution)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/speechfy-tts.py (reported line 134)May include surrounding context.

python
edge_cmd = resolve_edge_cmd()
    tmp = output_path + ".edge.mp3"
    try:
        subprocess.run(
            [edge_cmd, "--voice", EDGE_VOICE,
             "--text", text,
             "--write-media", tmp],

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/speechfy-tts.py (reported line 142)May include surrounding context.

python
)
        # edge-tts grava MP3 mesmo com extensão .ogg — converte para Opus
        # para garantir voice bubble nativa no Telegram.
        subprocess.run(
            ["ffmpeg", "-y", "-i", tmp,
             "-c:a", "libopus", "-b:a", "32k",
             output_path],

Static analysis

No suspicious patterns detected.