Back to skill

Security audit

Novel2voice-把小说发给skill,skill自动调用MIMO TTS/EDGE TTS处理小说文本或视频字幕→ 转化成多角色有声书、字幕音频。 自动识别角色、分配音色、情感标注,支持 Edge TTS(500+音色)和 MiMo TTS。 Use when user provides novel/story text or video subtitle file (.srt/.ass) and asks for audiobook, voice narration, or TTS generation. 触发词:有声书、小说转语音、字幕转语音、朗读、配音、TTS、多角色语音、视频配音。

Security checks across malware telemetry and agentic risk

Overview

The skill mostly matches its audiobook purpose, but it can send user text to remote TTS services and automatically use or persist API keys in ways users should review first.

Install only if you are comfortable with your novel or subtitle text being sent to the configured TTS services. Avoid using private manuscripts or confidential subtitles unless you trust the endpoint. Prefer environment variables or a managed secret store over pasting API keys into chat, review or remove any skill-local .env file after use, and be aware that the skill may read ~/.openclaw/openclaw.json for a MiMo/Xiaomi key.

SkillSpector

By NVIDIA
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (33)

subprocess module call

Medium
Category
Dangerous Code Execution
Content
sil_line = "file '" + silence_path + "'\n"
                    f.write(sil_line)

        subprocess.run([
            "ffmpeg", "-y", "-f", "concat", "-safe", "0", "-i", list_path,
            output_path
        ], capture_output=True, timeout=300)
Confidence
83% confidence
Finding
subprocess.run([ "ffmpeg", "-y", "-f", "concat", "-safe", "0", "-i", list_path, output_path ], capture_output=True, timeout=300)

Tainted flow: 'endpoint' from os.environ.get (line 345, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Content
for attempt in range(3):
        try:
            resp = requests.post(
                endpoint,
                json=payload,
                headers={
Confidence
92% confidence
Finding
resp = requests.post( endpoint, json=payload, headers={ "Content-Type": "application/json", "Authori

Tainted flow: 'endpoint' from os.environ.get (line 345, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Content
for endpoint in endpoints:
      for attempt in range(3):
        try:
            resp = requests.post(
                endpoint,
                json=payload,
                headers={
Confidence
94% confidence
Finding
resp = requests.post( endpoint, json=payload, headers={ "Content-Type": "application/json", "Authori

Lp3

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding
The skill clearly performs shell execution, file reads/writes, environment access, and network calls, yet it declares no permissions. This creates a transparency and policy-enforcement gap: a host may invoke the skill assuming low privilege while the documented workflow can install packages, call external TTS endpoints, and persist files or secrets locally.

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding
The documented behavior exceeds the stated purpose by including translation import/export, subtitle rewriting, local config and .env reads, and persistence of API keys. Such hidden or under-described capabilities are dangerous because they expand data handling and trust boundaries beyond what a user or platform reviewer would expect from a 'novel to voice' skill.

Intent-Code Divergence

Medium
Confidence
97% confidence
Finding
The guardrail claims API keys are only read from environment variables, but the workflow instructs saving user-supplied keys into a local .env file. This inconsistency can mislead users and auditors about secret storage, increasing the risk of credential exposure through local files, backups, repository inclusion, or permissive file permissions.

Context-Inappropriate Capability

Medium
Confidence
96% confidence
Finding
The skill explicitly instructs the agent to request a user's MiMo API key and persist it in a local `.env` file. Storing credentials in plaintext through conversational flow increases the chance of accidental disclosure via logs, filesystem access, backups, or later prompt/context exposure, especially because the skill normalizes long-term reuse of the secret.

Context-Inappropriate Capability

Medium
Confidence
95% confidence
Finding
The skill reads credentials from the environment, a local .env file, and '~/.openclaw/openclaw.json', which extends trust boundaries beyond the immediate audiobook task. Pulling API keys from another app's config can unintentionally expose unrelated secrets to this skill and any subprocesses it launches, especially because later code forwards environment state to child processes.

Context-Inappropriate Capability

Medium
Confidence
88% confidence
Finding
The skill silently reads an API key from ~/.openclaw/openclaw.json, which is an unrelated local credential store. This expands the skill's access beyond its declared inputs and can cause unintended credential use or cross-tool secret exposure without clear user consent.

Context-Inappropriate Capability

Medium
Confidence
96% confidence
Finding
The script silently reads a MiMo API key from $HOME/.openclaw/openclaw.json, which is outside the documented TTS-specific configuration path and belongs to an unrelated local tool context. This broadens the trust boundary, can exfiltrate or repurpose credentials without explicit user consent, and makes the script use secrets a caller did not intentionally provide for this skill.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The README advertises TTS generation using Edge TTS and optionally MiMo TTS but does not clearly disclose that user-provided novel text or subtitle content may be transmitted to third-party services. Because these inputs can contain copyrighted, personal, confidential, or unpublished material, users may unknowingly expose sensitive content outside their local environment.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The skill asks for a user API key and says it will save it to a local .env file without clearly warning about persistence, filesystem exposure, and reuse risks. Secrets written to local files can be leaked through logs, backups, other local users, accidental commits, or insecure permissions.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The document tells the agent to save a user-provided API key into a local `.env` file without warning the user that the credential will be stored persistently in plaintext. This creates an informed-consent and secret-handling problem: users may disclose sensitive credentials without understanding retention, exposure surface, or recovery procedures.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The scripted first-run prompt actively encourages users to provide an API key and promises local saving for future use, but omits basic safety guidance about plaintext persistence and secret exposure. Because this is user-facing language, it directly increases the likelihood that users hand over credentials under unsafe assumptions.

Missing User Warnings

Medium
Confidence
99% confidence
Finding
The script uses os.environ.get("EDGE_TTS_KEY", "sk-1234567890"), which embeds a default credential-like value and silently proceeds if the real secret is missing. This can cause accidental use of an invalid or unintended key, normalize insecure secret handling, and mask configuration problems that should fail closed.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
Reading a MiMo API key from a local credential file without user-facing disclosure creates a secret-sourcing transparency problem and can unexpectedly use credentials belonging to another tool or workflow. In a shared agent environment, this undermines least surprise and least privilege.

Missing User Warnings

Medium
Confidence
87% confidence
Finding
The skill sends input text to a remote TTS endpoint, but there is no in-code evidence of user-facing disclosure or consent about external transmission. For a narration skill, remote transmission is contextually expected, but undisclosed upload of potentially sensitive novel, subtitle, or manuscript content is still a privacy risk.

Missing User Warnings

Medium
Confidence
87% confidence
Finding
The MiMo branch uploads text content to a third-party API without any visible user-facing disclosure in this module. Because users may provide unpublished or sensitive text, lack of transparency increases privacy and compliance risk even if remote TTS is functionally necessary.

Ssd 3

Medium
Confidence
97% confidence
Finding
The skill establishes a workflow where the agent solicits, stores, and reuses a user credential from conversational input. This is dangerous because it turns the agent into a secret-collection and persistence channel, expanding the attack surface to chat history, intermediate tooling, local files, and any process that later reads `.env` contents.

Ssd 3

Medium
Confidence
97% confidence
Finding
The example onboarding text explicitly asks for the API key and states that it will be saved locally for later use. This normalizes unsafe credential handling and could lead to unnecessary retention of sensitive data beyond the immediate session, increasing risk of leakage or misuse.

Env Variable Harvesting

High
Category
Data Exfiltration
Content
2. ~/.openclaw/openclaw.json
    3. skill 本地 .env 配置
    """
    api_key = os.environ.get("MIMO_API_KEY", "")
    if api_key:
        return api_key
Confidence
94% confidence
Finding
os.environ.get("MIMO_API_KEY

Env Variable Harvesting

High
Category
Data Exfiltration
Content
if not os.path.exists(tts_python):
        tts_python = os.path.join(script_dir, "tts_voice.py")

    env = os.environ.copy()
    if tts_backend:
        env["TTS_BACKEND"] = tts_backend
    if cleaning_options:
Confidence
98% confidence
Finding
os.environ.copy()

Env Variable Harvesting

High
Category
Data Exfiltration
Content
if not os.path.exists(tts_python):
        tts_python = os.path.join(script_dir, "tts_voice.py")

    env = os.environ.copy()
    if tts_backend:
        env["TTS_BACKEND"] = tts_backend
    if cleaning_options:
Confidence
98% confidence
Finding
os.environ.copy()

External Transmission

Medium
Category
Data Exfiltration
Content
local http_code=""
  local max_attempts=3
  for attempt in $(seq 1 "$max_attempts"); do
    http_code=$(curl -s -w "%{http_code}" \
      -o "$work_dir/audio.wav" \
      --max-time 120 \
      -H "Content-Type: application/json" \
Confidence
91% confidence
Finding
curl -s -w "%{http_code}" \ -o "$work_dir/audio.wav" \ --max-time 120 \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $EDGE_TTS_KEY" \ -d

External Transmission

Medium
Category
Data Exfiltration
Content
local http_code=""
  local max_attempts=3
  for attempt in $(seq 1 "$max_attempts"); do
    http_code=$(curl -s -w "%{http_code}" \
      -o "$work_dir/resp.json" \
      --max-time 120 \
      -H "Content-Type: application/json" \
Confidence
90% confidence
Finding
curl -s -w "%{http_code}" \ -o "$work_dir/resp.json" \ --max-time 120 \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $MIMO_KEY" \ -d

VirusTotal

VirusTotal findings are pending for this skill version.

View on VirusTotal

Static analysis

No suspicious patterns detected.