Back to skill

Security audit

vociemaster

Security checks for vulnerabilities and agentic risk

Overview

This voiceover skill is mostly coherent, but it automatically saves detailed plaintext debug files containing user text and responses.

Review before installing if you will process confidential scripts, personal data, or proprietary content. The skill sends text to SenseAudio and, more importantly, helper.py automatically leaves a detailed .debug.json beside generated audio; delete those logs or modify the helper before using sensitive material. Keep the API key in the environment rather than source 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 (1)

T09 · Insecure Skill Coding Practices

Warning
Location
helper.py:393
Finding
Default Plaintext Debug Logging Exposes User Content and Complete API Responses<![CDATA[ ## Vulnerability Details **File Location**: `helper.py:393-406`, `helper.py:445-451`, `helper.py:517-520`, `helper.py:540-556`, `helper.py:688-712` **Vulnerability Type**: Plaintext storage of sensitive data **Risk Level**: Medium ### Vulnerable Code `helper.py:393-406` records the complete payload and request body for every attempt: ```python def _capture_attempt(attempt_logs, payload, headers, text_mode, payload_mode, attempt_index): entry = { "attempt": attempt_index, "text_mode": text_mode, "payload_mode": payload_mode, "voice_id": ((payload.get("voice_setting") or {}).get("voice_id")), "request_format": "application/json", "headers": _redact_headers(headers), "text_length": len(payload["text"]), "text_preview": _preview_text(payload["text"]), "payload": payload, "request_body_json": _json_dumps(payload), } attempt_logs.append(entry) return entry ``` `helper.py:445-451` records the complete API response: ```python with urllib.request.urlopen(request) as response: response_body = response.read() response_text = _decode_response_body(response_body) attempt_entry["response_status"] = response.status attempt_entry["response_headers"] = dict(response.headers.items()) attempt_entry["response_text"] = response_text ``` `helper.py:517-520` writes debug data to disk as plaintext JSON: ```python def _write_debug_log(debug_log_path, payload): if not debug_log_path: return _write_json(debug_log_path, payload) ``` `helper.py:540-556` includes complete text variants and request attempts in failure logs: ```python def _write_failure_debug_log(debug_log_path, args, text_variants, attempt_logs): payload = { "api_url": API_URL, "text_file": str(Path(args.text_file).resolve()), "output": str(Path(args.output).resolve()), "voice_id": args.voice_id, "speed": args.speed, "pitch": ...[truncated 4065 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Make debug logging explicitly opt-in. Do not derive and create a debug-log path unless `--debug-log` or a dedicated `--debug` flag is supplied. 2. Do not store complete request payloads, serialized bodies, text variants, metadata, or API response bodies in routine logs. 3. Record only minimal operational fields, such as attempt number, HTTP status, business status, text length, voice ID, and timing. 4. Explicitly remove `data.audio` before logging any API response. Avoid retaining even truncated audio payloads. 5. Redact or hash user text and metadata. If troubleshooting requires a preview, require explicit consent and impose a short, documented length limit. 6. Avoid recording absolute filesystem paths unless essential; use filenames or paths relative to the designated output directory. 7. Create opt-in debug files with restrictive permissions, such as mode `0600` on POSIX systems, and reject unsafe shared output locations where practical. 8. Define and document a retention policy, and provide an option to delete debug files automatically after successful processing. 9. Ensure failure reporting returns status codes and sanitized messages rather than complete remote response bodies. 10. Add tests verifying that normal synthesis creates only the requested audio output and that bearer tokens, source text, metadata, and audio hex are absent from logs. ]]>
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
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (14)

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding
声明描述强调的是短视频配音助手,核心卖点包括多角色音色映射、自动语速调节和 BGM 建议。但代码实际只提供两个子命令:synthesize 和 concat。synthesize 读取文本文件并调用 SenseAudio TTS 接口生成音频,支持可选的 voice、speed、pitch、vol 和音频格式参数;concat 仅通过 ffmpeg 进行音频拼接。代码中虽然有文本清洗、去角色前缀、重试、回退 voice_id、调试日志等辅助逻辑,但没有任何基于角色到音色的映射机制、没有自动计算语速的算法,也没有与 BGM 推荐相关的处理、模型调用或输出。因此声明与实际行为存在明显功能性不一致,且实际主用途更接近“通用 TTS 请求/拼接助手”而非所宣称的专业级短视频配音助手。

Ae1

High
Category
analysis-evasion
Content
先检查环境变量 `SENSEAUDIO_API_KEY`。如果已经存在,直接使用;如果不存在,再提示用户提供 API Key 或先在终端设置环境变量。不要把密钥写进 `SKILL.md`、脚本源码或提交记录。
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill declares powerful capabilities via required binaries, environment secret access, local file operations, network calls, and shell command examples, but it does not define an explicit tool scope or allowed-tools boundary. That makes the effective privilege surface broader and less auditable, increasing the chance an agent executes unintended shell/network actions with access to sensitive files or secrets.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
The manifest description and the full user-facing guidance force a specific language/locale for interaction. Under the policy, language constraints should either be optional for the user or clearly justified as region-specific; this file provides neither an opt-in nor a justification.

External Transmission

Medium
Category
Data Exfiltration
Content
API 地址固定为:

```text
https://api.senseaudio.cn/v1/t2a_v2
```

优先使用 `jq` 构造 JSON,避免转义错误。默认走非流式模式,便于直接拿到 `hex` 音频并落盘。
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
voice_id: $voice_id
    }
  }' |
curl -sS "https://api.senseaudio.cn/v1/t2a_v2" \
  -H "Authorization: Bearer $SENSEAUDIO_API_KEY" \
  -H "Content-Type: application/json" \
  --data-binary @-
Confidence
92% confidence
Finding
The skill sends user-provided text and an authorization bearer token to an external third-party API. This is expected for a cloud TTS workflow, but it is still a real data-exfiltration boundary: potentially sensitive scripts, prompts, or personal content leave the local environment, and misuse or logging by the third party could expose them.

External Transmission

Medium
Category
Data Exfiltration
Content
voice_id: $voice_id
    }
  }' |
curl -sS "https://api.senseaudio.cn/v1/t2a_v2" \
  -H "Authorization: Bearer $SENSEAUDIO_API_KEY" \
  -H "Content-Type: application/json" \
  --data-binary @-
Confidence
92% confidence
Finding
The skill sends user-provided text and an authorization bearer token to an external third-party API. This is expected for a cloud TTS workflow, but it is still a real data-exfiltration boundary: potentially sensitive scripts, prompts, or personal content leave the local environment, and misuse or logging by the third party could expose them.

External Transmission

Medium
Category
Data Exfiltration
Content
from pathlib import Path


API_URL = "https://api.senseaudio.cn/v1/t2a_v2"
MODEL_NAME = "SenseAudio-TTS-1.0"
FALLBACK_VOICE_IDS = ["child_0001_b", "male_0004_a", "male_0018_a"]
RETRYABLE_HTTP_STATUS_CODES = {500, 502, 503, 504}
Confidence
89% confidence
Finding
The code performs external transmission of user text and authorization credentials to a remote API endpoint, which is a real data-exposure boundary. In the context of a dubbing assistant, this may be functionally necessary, but it still creates privacy, compliance, and third-party trust risk if users are not clearly informed or if sensitive material is processed.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The helper transmits user-supplied text to a remote third-party TTS service without any explicit disclosure, consent flow, or local-only alternative. In this skill context, users may reasonably assume they are just generating audio, not exporting potentially sensitive script contents to an external provider, which raises privacy and data-governance concerns.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The code writes detailed debug logs containing full text variants, request payloads, and response bodies to disk automatically, including on failure. For a voiceover tool, input text may contain sensitive scripts, personal data, or proprietary content, so persistent local logging creates an unnecessary confidentiality risk and expands exposure if the host is shared or compromised.

Context-Inappropriate Capability

Medium
Confidence
90% confidence
Finding
The manifest describes a short-video dubbing assistant focused on voice mapping, speech-rate adjustment, and BGM suggestions. In this file, the skill also executes a local system binary via subprocess to concatenate arbitrary audio files, which is a broader host-execution capability than the manifest suggests and is not clearly justified by the stated scope.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
ffmpeg = "ffmpeg"
    try:
        subprocess.run(
            [ffmpeg, "-version"],
            check=True,
            stdout=subprocess.DEVNULL,
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
"copy",
            str(output),
        ]
        result = subprocess.run(cmd, capture_output=True, text=True, encoding="utf-8", errors="replace")
        if result.returncode != 0:
            raise SystemExit(result.stderr.strip() or "ffmpeg concat failed.")
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Natural-Language Policy Violations

Low
Confidence
73% confidence
Finding
The code fixes service use to a single provider endpoint under api.senseaudio.cn, which can impose a locale or regional routing choice on all users without opt-in. The policy calls for flagging language or locale constraints when they are forced rather than user-selectable or explicitly justified.

Static analysis

No suspicious patterns detected.