Back to skill

Security audit

Edge TTS

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a real text-to-speech skill, but it needs review because its helper scripts can write or delete arbitrary user-writable files when given unsafe paths and it sends text to an online TTS service.

Install only if you are comfortable sending TTS text to Microsoft's online service and running npm dependencies. Avoid using this skill on sensitive text, avoid unpinned npx examples, keep output paths in a dedicated folder, and do not use custom --config-path or --reset unless you have checked the target path.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/tts-converter.js:129
Finding

Unrestricted Output Path Allows Arbitrary File Overwrite

Content
View full analysis
', 'Output file path (default: temp file in system temp dir)') ``` It is subsequently passed to `textToSpeech` without path validation: ```javascript outputPath: options.output, ``` ### Technical Analysis The `--output` argument accepts an arbitrary filesystem path. The application neither constrains that path to an approved output directory nor checks whether the destination already exists, resolves through a symbolic link, or refers to a sensitive file. The path is passed directly to `node-edge-tts` as the destination for generated audio. Consequently, the behavior of the write operation is delegated to the dependency without enforcing application-level filesystem security boundaries. If subtitle generation is enabled, the library may also create a JSON file derived from the selected output path. This violates the principle of least privilege for filesystem operations. Even though the process cannot write beyond the privileges of the account running it, any writable file available to that account is potentially exposed to replacement or corruption. ### Attack Path 1. An attacker supplies or influences a TTS request that includes a crafted output path. 2. The Agent or user invokes the converter with an argument such as: ```bash node scripts/tts-converter.js "text" --output /path/to/writable/important-file ``` 3. Commander stores the path in `options.output`. 4. The a ...[truncated 1099 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/tts-converter.js:19
Finding

Predictable Shared Temporary Directory Enables Local File Interference and Disclosure

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/config-manager.js:96
Finding

Unrestricted Configuration Path Allows Arbitrary File Deletion During Reset

Content
View full analysis
', 'Path to config file') ``` ```javascript program.parse(process.argv); const options = program.opts(); const configPath = options.configPath || DEFAULT_CONFIG_PATH; async function main() { if (options.reset) { const config = await resetConfig(configPath); ``` ### Technical Analysis The `--config-path` argument is accepted as an unrestricted path and assigned directly to `configPath`. When `--reset` is supplied, `resetConfig()` passes that path to `fs.unlink()` without checking whether it refers to the intended TTS configuration file. No canonicalization, approved-directory restriction, filename check, ownership validation, or symbolic-link protection is applied. As a result, any regular file that the executing account can unlink may be selected as the reset target. The function also suppresses every `unlink()` error rather than only ignoring `ENOENT`. This conceals permission failures, invalid target types, and other security-relevant errors, making attempted misuse and operational problems harder to detect. ### Attack Path 1. An attacker persuades or causes the Agent to invoke the configuration manager with a crafted path: ```bash node scripts/config-manager.js --config-path /path/to/writable/important-file --reset ``` 2. Commander records the attacker-selected path. 3. The application assigns it directly to `configPath`. 4. `resetConfig()` calls `fs.unlink(configPath)`. 5. If the executing acc ...[truncated 974 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (18)

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

The declared description presents the skill as a text-to-speech converter that generates audio from text. However, the supplied code chunk does not synthesize speech, process input text, call node-edge-tts, or generate subtitles/audio files. Its primary purpose is managing persistent TTS preferences via a JSON config file and exposing CLI operations to get/set/reset/export those settings or convert them into command-line arguments. While the managed settings relate to TTS features mentioned in the description, this code chunk's behavior is materially different from actual text-to-speech conversion and includes undeclared local filesystem access for storing configuration.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: ws==8.19.0 — 2 advisory(ies): CVE-2026-45736 (ws: Uninitialized memory disclosure); CVE-2026-48779 (ws: Memory exhaustion DoS from tiny fragments and data chunks)

High
Category
Supply Chain
Confidence
95% confidence
Finding

The lockfile pins a transitive dependency to ws 8.19.0, and the finding cites known advisories for uninitialized memory disclosure and memory-exhaustion denial of service in that version. Because this skill performs networked text-to-speech using node-edge-tts, a vulnerable WebSocket client library is plausibly reachable during normal operation, making the issue relevant rather than purely theoretical.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

A broad trigger such as any user request containing "tts" can cause unintended activation in ordinary conversation, especially in multi-skill environments where keyword collisions are common. This can lead to unnecessary processing, unintended audio generation, or accidental transmission of user text to the external TTS service without sufficiently clear user intent.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The instruction to activate on "triggers or user request" is underspecified and leaves too much discretion to the agent, increasing the chance that non-TTS content will be converted or routed externally. In this skill, that ambiguity matters because text may be sent to Microsoft's online TTS service and written to local temporary storage.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

Relying on the "tts" keyword alone, without contextual constraints, negative examples, or confirmation logic, creates a realistic risk of false activation. Because the skill uses an online service and may generate persistent artifacts in temp storage, mistaken invocation has privacy and operational consequences beyond a harmless formatting error.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
80% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

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

md
- Output is MP3 format by default
- Requires internet connection
- Supports subtitle generation (JSON format with word-level timing)
- **Temporary File Handling**: By default, audio files are saved to the system's temporary directory (`/tmp/edge-tts-temp/` on Unix, `C:\Users\<user>\AppData\Local\Temp\edge-tts-temp\` on Windows) with unique filenames (e.g., `tts_1234567890_abc123.mp3`). Files are not automatically deleted - the calling application (Clawdbot) should handle cleanup after use. You can specify a custom output path with the `--output` option if permanent storage is needed.
- **TTS keyword filtering**: The skill automatically filters out TTS-related keywords (tts, TTS, text-to-speech) from text before conversion to avoid converting the trigger words themselves to audio
- For repeated preferences, use `config-manager.js` to set defaults
- **Default voice**: `en-US-MichelleNeural` (female, natural)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The guide states that the module uses Microsoft's online TTS service, but it does not clearly warn users that input text will be transmitted to a third-party service and may contain sensitive information. In a TTS skill, users may submit private messages, credentials, or regulated data, so the lack of prominent privacy disclosure increases the risk of accidental data exposure.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
92% confidence
Finding

The documentation instructs users to run npx node-edge-tts without pinning a specific version, which can cause execution of whatever package version is current at runtime. This creates a supply-chain risk: if a malicious or compromised version is published, users may execute unreviewed code directly from the registry.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
92% confidence
Finding

This example uses npx node-edge-tts without a version pin, so users may execute a newer or tampered package than the author intended. Because npx fetches and runs code, this exposes users to registry compromise, package takeover, or unexpected breaking behavior.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
92% confidence
Finding

The unpinned npx node-edge-tts command allows arbitrary future package versions to be executed, which is a common software supply-chain hazard. In a skill guide, users may copy-paste the command directly, increasing the chance of unsafe execution.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
92% confidence
Finding

Using npx node-edge-tts without a fixed version means the command is not reproducible and may run untrusted code if the package is updated maliciously or compromised. This is especially risky in documentation because it normalizes direct execution of remote package code.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
92% confidence
Finding

This command again relies on unpinned npx execution, which exposes users to package substitution and malicious-update risks. Since it is a copyable example, the skill content could indirectly lead users to execute unexpected code from the npm ecosystem.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
90% confidence
Finding

The later subtitle example also shows npx node-edge-tts without version pinning, carrying the same npm supply-chain execution risk as earlier occurrences. Repetition throughout the guide increases the likelihood users will follow the unsafe pattern.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill sets both the default voice and language to en-US values, which establishes a specific language/locale by default rather than offering a neutral choice or explicit opt-in. This can violate language/locale policy when users have not chosen English or a US locale.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
93% confidence
Finding

The test script invokes npx node-edge-tts without pinning an exact package version. If the package is not already installed locally or resolution behavior changes, npx may fetch and execute code from the registry, creating a supply-chain risk where a malicious or compromised version could run during testing.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The script silently modifies user-supplied content by removing words such as 'tts' and 'text-to-speech' before synthesis, despite presenting itself as a straightforward text-to-speech converter. This hidden transformation can change meaning, violate user expectations, and create integrity issues in workflows that require faithful audio rendering of exact input text.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
87% confidence
Finding

The dependency node-edge-tts is specified with a caret range, which allows newer compatible versions to be installed automatically. This increases supply-chain exposure because builds are not fully reproducible and a compromised upstream release could be pulled in without deliberate review.

Content

Scanner excerpt · scripts/package.json (reported line 12)May include surrounding context.

json
"test": "npx node-edge-tts -t \"Hello, world! This is a test of the Edge TTS service.\" -f test-output.mp3 && echo \"Test completed successfully!\""
  },
  "dependencies": {
    "node-edge-tts": "^1.2.9",
    "commander": "^11.0.0"
  },
  "author": "Clawdbot",

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
84% confidence
Finding

The dependency commander is also unpinned via a caret range, allowing silent drift to later releases. While common in development, this weakens build integrity and can introduce vulnerable or malicious upstream code unexpectedly.

Content

Scanner excerpt · scripts/package.json (reported line 13)May include surrounding context.

json
},
  "dependencies": {
    "node-edge-tts": "^1.2.9",
    "commander": "^11.0.0"
  },
  "author": "Clawdbot",
  "license": "MIT"

Static analysis

No suspicious patterns detected.