Back to skill

Security audit

Edge TTS CN

Security checks for vulnerabilities and agentic risk

Overview

This is a real text-to-speech skill, but it needs review because it can send user text to an online service, uses broad triggers, leaves generated audio on disk, and includes supply-chain risk.

Install only if you are comfortable with text being sent to Microsoft Edge's online TTS service. Do not use it for secrets, credentials, private business data, or sensitive personal content unless you have reviewed the data-handling implications. Review or update the npm dependencies before use, prefer pinned installs, and clean up generated MP3/JSON files from the temp directory after use.

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

T09 · Insecure Skill Coding Practices

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

Insecure Temporary Storage and Retention of Synthesized Speech Data

Content
View full analysis

Vulnerability Details

File Location: scripts/tts-converter.js:18-20, 55-71, 128-129, 155-171; retention behavior documented in SKILL.md:198
Vulnerability Type: Unsafe temporary-file handling and sensitive data retention
Risk Level: Medium

Vulnerable Code

javascript
const DEFAULT_TIMEOUT_MS = 10000;
const MAX_TEXT_LENGTH = 10000;
const TEMP_DIR = path.join(os.tmpdir(), 'edge-tts-temp');
javascript
async function ensureTempDir() {
  try {
    await fs.access(TEMP_DIR);
  } catch (error) {
    await fs.mkdir(TEMP_DIR, { recursive: true });
  }
}

function generateTempPath(extension = '.mp3') {
  const timestamp = Date.now();
  const random = Math.random().toString(36).substring(2, 8);
  const filename = `tts_${timestamp}_${random}${extension}`;
  return path.join(TEMP_DIR, filename);
}
javascript
await ensureTempDir();
const finalOutputPath = outputPath || generateTempPath('.mp3');
javascript
await tts.ttsPromise(filteredText, finalOutputPath);

const stats = await fs.stat(finalOutputPath);
console.log(`\n✓ Audio saved to: ${finalOutputPath}`);
console.log(`✓ File size: ${stats.size} bytes`);

if (saveSubtitles) {
  const subtitlePath = finalOutputPath.replace(/\.[^/.]+$/, '.json');
  try {
    const subStats = await fs.stat(subtitlePath);
    console.log(`✓ Subtitles saved to: ${subtitlePath}`);
    console.log(`✓ Subtitle size: ${subStats.size} bytes`);
  } catch (e) {
    console.log(`ℹ  No subtitles generated`);
  }
}

The documented retention behavior is:

markdown
Files are not automatically deleted - the calling application (Clawdbot) should handle cleanup after use.

Technical Analysis

Synthesized audio and optional subtitle data are stored under a fixed directory in the operating system's shared temporary area. The directory is created without an explicit restrictive permission mode, and the ...[truncated 2286 chars]

Remediation
View remediation

Remediation Suggestions

  1. Create a private per-invocation temporary directory using fs.mkdtemp() beneath os.tmpdir().
  2. Explicitly set the directory mode to 0700 and generated file modes to 0600.
  3. Use crypto.randomUUID() or cryptographically secure random bytes instead of Math.random().
  4. Create output files atomically with exclusive-create semantics where supported, preventing reuse of attacker-controlled paths.
  5. Validate that the temporary directory is owned by the current user and is not a symbolic link before writing.
  6. Delete temporary MP3 and JSON files in a finally block after successful delivery, unless the caller explicitly requests permanent storage.
  7. Add bounded retention as a fallback, such as deleting stale files on startup and enforcing maximum age and directory size.
  8. Avoid logging complete sensitive paths in shared logs unless operationally necessary.
  9. For caller-supplied permanent output paths, document overwrite behavior and consider rejecting symbolic links or requiring an explicit overwrite option.
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 (22)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The declared description says the skill performs text-to-speech conversion and generates audio. The supplied code does not synthesize speech, process input text, call node-edge-tts, or create audio/subtitle outputs. Its primary purpose is managing persistent TTS preferences via a JSON file and exposing a CLI for getting/setting/resetting/exporting those settings. The filesystem persistence in ~/.tts-config.json is also an undeclared capability/resource access, though it is related to TTS support. Overall, this chunk materially differs from the declared primary behavior, so it should be flagged as a mismatch.

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
94% confidence
Finding

The lockfile pins ws to 8.19.0, and the provided advisory information identifies two HIGH-severity issues affecting that version: uninitialized memory disclosure and memory-exhaustion denial of service. Because this skill performs TTS through node-edge-tts, which depends on ws for network communication, a vulnerable WebSocket client library in this context could expose memory contents or allow a remote service or attacker-in-the-middle to destabilize the process through crafted fragmented frames.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The installation and usage guidance documents an internet connection requirement but does not clearly warn users that the text submitted for TTS will be transmitted to an external service. In a TTS skill, users may paste sensitive prompts, notes, credentials, or personal data; without an explicit privacy warning, they may unknowingly disclose that content to a third party.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill uses a very broad activation heuristic based on the generic keyword "tts" and loosely defined intent detection. This can cause the agent to invoke audio generation in contexts where the user did not actually request speech output, leading to unintended processing, disclosure of text to an external TTS service, or surprising side effects.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The guidance to detect TTS intent from "triggers or user request" is underspecified and leaves too much discretion to the agent. In a skill that sends content to an online TTS backend, ambiguous routing increases the chance that sensitive or irrelevant user text is transmitted off-box without clear intent.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

Recognizing the standalone keyword "tts" as sufficient for activation without negative examples or contextual validation is unsafe in an agent environment. It increases accidental invocation risk and may expose arbitrary nearby text to conversion and external network transmission when the mention was incidental rather than instructive.

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)

Rp1

Medium
Category
MCP Rug Pull
Confidence
95% confidence
Finding

The guide instructs users to run npx node-edge-tts without pinning an exact package version, which causes execution of whatever version is current at install time. If the package is updated maliciously, compromised, or introduces a breaking security issue, 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
95% confidence
Finding

This command example uses npx node-edge-tts without a pinned version, so execution depends on the latest registry state rather than a reviewed artifact. In documentation for an agent skill, that increases supply-chain risk because operators may copy-paste and run it directly.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
95% confidence
Finding

The unpinned npx invocation allows a different package version to be fetched and executed over time, making builds and manual runs non-reproducible. A compromised or typosquatted package release could lead to arbitrary code execution on the host running the command.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
95% confidence
Finding

This example again promotes execution of an unpinned npm package via npx, which is a standard supply-chain exposure. In the context of a skill reference, examples are likely to be executed verbatim, increasing the practical chance of exploitation if the package source changes.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
95% confidence
Finding

Because npx node-edge-tts is unpinned here, anyone following the documentation may run code that differs from what the author tested. That creates a supply-chain execution risk, especially for automation or agent-integrated workflows where commands may be adopted without further review.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding

The repeated unpinned npx example in the subtitles section has the same supply-chain weakness: it fetches and executes the latest package version at runtime. In an agent skill reference, repeated examples reinforce insecure operational habits and make accidental unsafe execution more likely.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
87% confidence
Finding

The test script invokes npx node-edge-tts without pinning an exact package version, which can cause execution of a newer or substituted package from the registry at run time. In CI, developer workstations, or automated validation pipelines, this creates a supply-chain risk because remote code may be fetched and executed unpredictably.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The usage/documentation states that the provided text is converted to speech, but the implementation later removes certain words before synthesis. This documentation/behavior mismatch is a security-relevant integrity issue because operators and users may rely on the tool for faithful spoken reproduction while the actual output can differ from the source text.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The code silently modifies user-provided content by stripping words like 'tts' and 'text-to-speech' before synthesis. In a TTS skill, users reasonably expect exact rendering of supplied text, so undisclosed alteration can misrepresent content, undermine user trust, and create integrity issues if the spoken output is used for accessibility, prompts, verification, or quoted speech.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill sends input text to Microsoft's online Edge TTS service, but it does not explicitly warn users that their content leaves the local environment. Because TTS requests may contain sensitive personal, business, or secret material, the lack of disclosure creates a privacy and data-handling risk that is more significant in an agent skill where users may assume local processing.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The trigger list includes the acronym "TTS"/"tts", which is highly ambiguous and may appear in unrelated contexts, increasing the chance of accidental activation. Although this skill is only for text-to-speech, the generic acronym makes routing less precise and can lead to confusing or unintended behavior in multi-skill environments.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The trigger phrase at line 11 is broad enough that ordinary user requests related to reading or speaking text could unintentionally activate this skill. In an agent ecosystem, unintended invocation can cause incorrect tool selection, unexpected audio generation, or data being sent to a TTS backend when the user did not explicitly request that action.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

The default config hard-codes both a specific voice and language locale (en-US-MichelleNeural and en-US). Under the policy for natural-language violations, forcing a specific language/locale without offering an explicit user choice or opt-in is a reportable issue.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
82% confidence
Finding

Using the semver range ^1.2.9 for node-edge-tts allows future minor/patch releases to be installed automatically, which can introduce unreviewed behavior or a compromised upstream release. Because this package is directly involved in executable TTS functionality, dependency drift increases supply-chain exposure.

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
79% confidence
Finding

Using the semver range ^11.0.0 for commander permits automatic upgrades to later compatible releases, reducing build reproducibility and increasing supply-chain risk if an upstream release is malicious or defective. Although commander is a common CLI helper and likely lower risk than direct execution tooling, it still runs in the application's process.

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.