Back to skill

Security audit

tts

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a real text-to-speech skill, but users should review it because it sends text to an online TTS service and has dependency and temporary-file risks.

Install only if you are comfortable with requested text being sent to Microsoft Edge's online TTS service. Avoid converting secrets, private messages, regulated data, or proprietary content. Prefer explicit TTS requests, choose an intentional output path for sensitive audio, clean up generated files, and update or audit npm dependencies before using this in automation.

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:19
Finding

Unsafe Shared Temporary Directory for Generated Audio

Content
View full analysis

Vulnerability Details

File Location: scripts/tts-converter.js, lines 19, 52–72, and 126–129
Vulnerability Type: Unsafe temporary-file handling
Risk Level: Medium

Vulnerable Code

javascript
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 });
  }
}

/**
 * Generate unique temporary file path
 * @param {string} extension - File extension (e.g., '.mp3')
 * @returns {string} Temporary file path
 */
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
// Ensure temp directory exists and use temp file if no output path specified
await ensureTempDir();
const finalOutputPath = outputPath || generateTempPath('.mp3');

Technical Analysis

The application stores generated audio in a fixed directory under the operating system's shared temporary directory. It checks only whether that path is accessible; it does not verify that the directory is owned by the current user, has restrictive permissions, or is not a symbolic link.

The fs.access() followed by fs.mkdir() sequence also introduces a time-of-check/time-of-use window. If the directory already exists, the application accepts it without validating its type or security properties. A local attacker may therefore pre-create or manipulate the shared path before the victim invokes the converter.

Temporary filenames combine the current timestamp with six characters generated by Math.random(). This is not a cryptographically secure source of randomness. Although exploitation requires local access and successful prediction or racing, monitoring the ...[truncated 1937 chars]

Remediation
View remediation

Remediation Suggestions

  1. Create a private directory for each invocation using fs.mkdtemp() beneath os.tmpdir() rather than reusing a global directory.
  2. Explicitly restrict the directory to the current user with mode 0700.
  3. Use crypto.randomUUID() or crypto.randomBytes() instead of Math.random() for output names.
  4. Validate temporary paths with fs.lstat() and reject symbolic links or unexpected filesystem object types.
  5. Where possible, create output files atomically with exclusive-create and no-follow semantics.
  6. Apply restrictive file permissions such as 0600 to generated audio and subtitle files.
  7. Delete temporary files and their per-run directory in a finally block after the calling application has delivered or copied the result.
  8. If files must persist, require an explicit user-selected output path and document the retention and confidentiality implications.
  9. Add tests that pre-create the temporary path as a symbolic link, directory owned by another user, and conflicting output file to ensure the converter fails securely.
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 (20)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The declared description presents this as a text-to-speech conversion skill that generates spoken audio from text. However, the supplied code only manages persistent user preferences for a TTS system: it loads/saves JSON config, exposes CLI options to set voice/language/rate/pitch/volume, toggles subtitle preferences, handles proxy/timeout, and prints equivalent CLI args. While these settings are related to TTS, the code chunk itself does not accept text input for synthesis, invoke node-edge-tts, generate audio, or create subtitle files. Its primary purpose is materially different: configuration management rather than TTS conversion. The file-system persistence behavior is also an undeclared capability, though it is supportive of the config-manager role.

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

The lockfile pins the transitive dependency ws to version 8.19.0, and the provided advisories indicate this version is affected by an uninitialized memory disclosure and a memory-exhaustion denial-of-service issue. In a TTS skill that relies on node-edge-tts and therefore network/WebSocket communication, processing attacker-controlled or remote service traffic could expose memory contents or allow resource exhaustion, making this a real supply-chain risk rather than a false positive.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The documentation instructs users to install and use a cloud-backed TTS tool but does not clearly warn that user-supplied text is transmitted to an external online service. This can cause accidental disclosure of sensitive prompts, personal data, or confidential content because users may reasonably assume text processing is local unless told otherwise.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The trigger guidance is broad enough that normal discussion of accessibility, multitasking, driving, or cooking could cause the skill to activate and send unintended text to TTS processing. Because this skill uses an online third-party service, accidental invocation can expose user content externally and generate audio actions the user did not explicitly request.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill uses Microsoft Edge’s online TTS service, but the primary description and trigger flow do not clearly warn that input text leaves the local environment. This creates a privacy and data-handling risk, especially if users ask to vocalize sensitive messages, summaries, or search results under the assumption processing is local.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

Relying on the bare keyword 'tts' without boundary rules is prone to false activations in ordinary conversation, logs, filenames, or quoted text. In this skill’s context, a false activation can cause arbitrary nearby text to be transmitted to the remote TTS service or converted into audio without clear user consent.

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 Edge's online TTS service, but it does not clearly warn that supplied text is transmitted to an external network service. In a skill context, users may pass sensitive prompts, secrets, or private content to TTS, so missing privacy disclosure can cause unintended data exfiltration to a third party.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
95% confidence
Finding

The documentation recommends executing npx node-edge-tts without pinning a specific version, which allows whatever package version is current in the registry at execution time to be fetched and run. In an agent or automated environment, this creates supply-chain risk because a compromised new release or dependency could execute attacker-controlled code.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
95% confidence
Finding

This example invokes npx node-edge-tts directly from the registry without version pinning. If users or agents copy this command, they may execute an unexpected or malicious future package version, making this a real supply-chain exposure.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
95% confidence
Finding

The command-line example fetches and runs node-edge-tts without constraining the version. In environments where agents may automatically follow documentation, this increases the chance of running unreviewed code from a package update or takeover.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
95% confidence
Finding

This unpinned npx example exposes consumers to package substitution or malicious update risk because the executed artifact is resolved at runtime. The danger is heightened for skills or bots that may operationalize example commands without human review.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
95% confidence
Finding

By documenting npx node-edge-tts without a version, the guide normalizes execution of mutable third-party code. A compromised package release could lead to arbitrary code execution on the host that runs the command.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
95% confidence
Finding

The subtitles example again relies on unpinned npx execution, inheriting the same supply-chain risk as the other occurrences. Because this is a reference guide likely to be copied verbatim, the unsafe pattern is actionable and real rather than theoretical.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill sets voice: 'en-US-MichelleNeural' and lang: 'en-US' as defaults, which effectively imposes a specific language/locale choice. The file provides options to change these values later, but the initial behavior is still forced rather than explicitly user-selected or documented as a justified region-specific constraint.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
97% confidence
Finding

The test script invokes npx node-edge-tts without pinning an exact package version. npx may resolve and execute a different package version than the one intended, which creates a supply-chain risk if a newer compromised release is fetched during testing or CI. In this skill context, the command is directly related to TTS functionality and likely to be run by maintainers, making unexpected remote package execution more plausible.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The script sends arbitrary input text to Microsoft Edge's online TTS service via the node-edge-tts library, but it does not clearly warn users that their content leaves the local system. In a skill intended for general text conversion, users may provide sensitive prompts, credentials, personal data, or proprietary content, creating a real privacy and data-handling risk even though this is not obviously malicious.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

This markdown file includes CLI examples that create output.mp3 and output.json, and later states these files are generated, but it does not explicitly warn users that running the commands will write files to the current workspace. For markdown files, SQP-2 applies when the description omits warnings about behaviors that could affect user data or system state.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
90% confidence
Finding

The dependency node-edge-tts is specified with a caret range (^1.2.9), which permits automatic adoption of future minor and patch releases. This weakens build reproducibility and increases supply-chain exposure if an upstream release is malicious or introduces a vulnerable change. Because this package is central to the skill's core functionality, compromise of this dependency could affect all TTS operations.

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

The dependency commander is also specified with a caret range (^11.0.0), allowing non-deterministic upgrades. While this is a common practice, it still creates a supply-chain risk because future releases can change behavior or become compromised and then be pulled into installs automatically. In this package, commander is a supporting CLI dependency, so the direct impact is lower than a compromise of the main TTS library.

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"