Back to skill

Security audit

Autonoannounce

Security checks for vulnerabilities and agentic risk

Overview

This skill mostly matches its local TTS purpose, but its playback and configuration scripts expose avoidable command-execution and file-write risks that users should review before installing.

Install only if you trust the skill package and are comfortable with it using your ElevenLabs API key, sending synthesis/preflight requests to ElevenLabs, playing local audio, and writing local config/audio state. Before routine use, restrict playback backends to a fixed allowlist, fix the PowerShell invocation to pass filenames as data, constrain earcon library writes to the skill state directory, and replace fixed /tmp response files with private temporary files.

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 (4)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/play-local-audio.sh:71
Finding

Configuration-Controlled Arbitrary Command Execution Through Custom Playback Backend

Content
View full analysis
/dev/null 2>&1; then exec "$BACKEND" "$FILE" fi echo "unknown/unavailable backend: $BACKEND" >&2 exit 1 ;; ``` ### Technical Analysis The playback backend can be loaded from `config/tts-queue.json`. Although known backends are handled by dedicated branches, the default branch permits any value that resolves through `command -v`. The selected executable is then launched as: ```bash exec "$BACKEND" "$FILE" ``` Shell metacharacters inside `BACKEND` are not directly interpreted because the variable is quoted. Nevertheless, the absence of an executable allowlist creates an arbitrary program execution primitive. An attacker can select an interpreter such as `bash`, `python3`, or another executable available through `PATH`. The supplied audio-file argument then becomes input to that executable. For example, if `playback.backend` is set to `bash` and the requested “audio file” is an existing shell script, the script is executed rather than played. ### Attack Path 1. The attacker obtains the ability to modify `config/tts-queue.json`, influence first-run setup values, or otherwise control the playback backend argument. 2. The attacker sets `playback.backend` to an interpreter or attacker-controlled executable available through `PATH`. 3. The attacker creates or selects an existing file that passes the script's ` ...[truncated 773 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/play-local-audio.sh:65
Finding

PowerShell Command Injection Through an Audio Filename

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/earcon-library.sh:43
Finding

Arbitrary Filesystem Write Through Unrestricted Earcon Library Path

Content
View full analysis
"$LIB_PATH" } ``` ```python def awrite(path,obj): d=os.path.dirname(path) fd,tmp=tempfile.mkstemp(dir=d,prefix='.tmp-',text=True) with os.fdopen(fd,'w') as f: json.dump(obj,f,indent=2) f.write('\n') os.replace(tmp,path) awrite(cfgp,cfg) awrite(libp,lib) ``` ### Technical Analysis The `earcons.libraryPath` value is loaded from `config/tts-queue.json` and treated as a trusted filesystem destination. Absolute paths are explicitly accepted. Relative paths are appended to the project root without canonicalization, so traversal sequences can also escape the expected directory. The `init` operation creates the selected path if it does not exist. During metadata updates, Python writes a temporary file in the selected destination directory and atomically replaces the configured library file. Atomic replacement protects against partial writes but does not restrict the destination. Consequently, control over the configuration can be converted into creation or replacement of an attacker-selected file writable by the current user. Replacement requires the destination to contain JSON compatible with the preceding `json.load`, but that still includes many application configuration and state files. ### Attack Path 1. The attacker modifies `earcons.libraryPath` in `config/tts-queue.json`. 2. The attacker supplies either: - An absolute path outside the project, or - A relative path containing traversal components such as `../`. 3. The attacker invokes `earcon-library.sh init` to ...[truncated 815 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/elevenlabs-preflight.sh:47
Finding

Predictable Shared Temporary Files Allow Symlink-Based File Overwrite

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (17)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The skill presents itself as an operational TTS pipeline but also exposes first-run/setup execution not described in the declared purpose. Undisclosed initialization or installation behavior can expand attack surface through environment changes, dependency setup, or filesystem modifications that reviewers did not expect.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The skill presents itself as an operational TTS pipeline but also exposes first-run/setup execution not described in the declared purpose. Undisclosed initialization or installation behavior can expand attack surface through environment changes, dependency setup, or filesystem modifications that reviewers did not expect.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

The skill presents itself as an operational TTS pipeline but also exposes first-run/setup execution not described in the declared purpose. Undisclosed initialization or installation behavior can expand attack surface through environment changes, dependency setup, or filesystem modifications that reviewers did not expect.

Content

No source excerpt is available for this finding.

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
70% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · references/runbook.md (reported line 12)May include surrounding context.

Quick checks:

bash
printenv ELEVENLABS_API_KEY | wc -c
printenv ELEVENLABS_VOICE_ID | wc -c
skills/autonoannounce/scripts/playback-probe.sh auto
skills/autonoannounce/scripts/playback-validate.sh

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill advertises shell execution, environment-variable use, and file writes but does not declare an explicit tool scope such as permissions or allowed-tools. That omission weakens reviewability and least-privilege enforcement, making it easier for an agent to invoke broader capabilities than a user would reasonably infer from the metadata.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% 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/earcon-library.sh (reported line 139)May include surrounding context.

sh
ts=$(date +%s)
    out="$EARCON_DIR/${category}-${ts}.mp3"
    code=$(curl -sS -o "$out" -w '%{http_code}' -X POST "https://api.elevenlabs.io/v1/sound-generation" \
      -H "xi-api-key: ${ELEVENLABS_API_KEY}" \
      -H 'Content-Type: application/json' \
      -d "{\"text\":\"$prompt\",\"duration_seconds\":$duration}")

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/earcon-library.sh (reported line 139)May include surrounding context.

sh
ts=$(date +%s)
    out="$EARCON_DIR/${category}-${ts}.mp3"
    code=$(curl -sS -o "$out" -w '%{http_code}' -X POST "https://api.elevenlabs.io/v1/sound-generation" \
      -H "xi-api-key: ${ELEVENLABS_API_KEY}" \
      -H 'Content-Type: application/json' \
      -d "{\"text\":\"$prompt\",\"duration_seconds\":$duration}")

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The script sends the user-supplied or default prompt to ElevenLabs via an HTTP POST request. Although usage notes mention the API key requirement, the generate path itself does not disclose that prompt content is transmitted to a third-party service, which is a privacy-relevant network operation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

This shell script reads the ELEVENLABS_API_KEY from the environment and uses it in multiple curl requests to the ElevenLabs API, including a POST request that transmits request data. While the code handles missing credentials, it does not provide a user-facing warning, confirmation, or explanatory comment/docstring disclosing that it will use the credential and contact an external service.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% 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/elevenlabs-preflight.sh (reported line 47)May include surrounding context.

sh
*) echo 404; return 0 ;;
    esac
  fi
  code=$(curl -sS -o /tmp/el_preflight.json -w '%{http_code}' "${h[@]}" "$BASE$ep")
  echo "$code"
}

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/setup_first_run.py (reported line 18)May include surrounding context.

python
def detect_backend() -> str:
    script = SCRIPTS / "backend-detect.sh"
    try:
        out = subprocess.check_output([str(script)], text=True).strip()
        return out or "auto"
    except Exception:
        return "auto"

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/setup_first_run.py (reported line 27)May include surrounding context.

python
def probe_devices(backend: str) -> list[str]:
    script = SCRIPTS / "playback-probe.sh"
    try:
        out = subprocess.check_output([str(script), backend], text=True)
    except Exception:
        return []
    devices = []

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/setup_first_run.py (reported line 98)May include surrounding context.

python
cmd = [str(SCRIPTS / "playback-test.sh"), "--backend", backend]
            if device:
                cmd += ["--device", device]
            subprocess.call(cmd)
            heard = prompt("Did you hear it? (y/n)", "y")
            if not heard.lower().startswith("y"):
                print("Tip: rerun setup and choose a different backend/device.")

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/setup_first_run.py (reported line 143)May include surrounding context.

python
if cfg["earcons"]["enabled"] and generate and generate.lower().startswith("y"):
        gen_script = SCRIPTS / "earcon-library.sh"
        for cat in ["start", "end", "update", "important", "error"]:
            subprocess.call([str(gen_script), "generate", cat, f"{style} {cat} notification sound", "1"])
        print("Starter earcons generated (where API/key permits).")

    return 0

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
80% confidence
Finding

The generate path creates an MP3 at a timestamped location and updates config/library metadata, which are file-writing operations. While the script prints a completion message after success, there is no prior warning, confirmation, or descriptive comment/docstring near the operation indicating that running generate will persist new files and modify configuration state.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

In noninteractive mode, the script assigns defaults and proceeds to write a configuration file containing playback settings and a voice ID sourced from CLI or environment variables, but it provides no prior disclosure before persisting that data. The file write is only announced after completion, and the noninteractive path skips the interactive prompts that otherwise provide context about what is being configured.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

This shell script overwrites or creates the file at "$ROOT/config/tts-queue.json" using a here-document, which is a file write affecting local configuration state. While the file is part of a test setup, there is no inline comment, prompt, or explicit warning near the write to disclose that the script modifies user or repository configuration.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.