Back to skill

Security audit

senseaudio的tts工具,根据用户需求生成文案完成配音

Security checks for vulnerabilities and agentic risk

Overview

The skill does what it claims by sending text to SenseAudio for speech generation, but it has under-scoped credential and dependency risks users should review before installing.

Install only if you are comfortable sending synthesis text to SenseAudio and using a SenseAudio API key. Before use, keep SENSEAUDIO_API_BASE unset or fixed to https://api.senseaudio.cn, and avoid running the skill in an environment where automatic pip installation could modify shared or privileged Python state. A safer version would remove runtime pip install behavior and validate the API base against an official allowlist.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/main.py:108
Finding
Configurable API Endpoint Can Exfiltrate the API Key and User Text<![CDATA[ ## Vulnerability Details **File Location**: `scripts/main.py`, lines 108-130 **Vulnerability Type**: Unrestricted destination for sensitive network requests **Risk Level**: High ### Vulnerable Code ```python class SenseAudioClient: def __init__(self, api_key: Optional[str] = None, api_base: Optional[str] = None): self.api_key = (api_key or os.getenv("SENSEAUDIO_API_KEY", "")).strip() self.api_base = (api_base or os.getenv("SENSEAUDIO_API_BASE", DEFAULT_API_BASE)).rstrip("/") self.api_url = f"{self.api_base}{DEFAULT_API_PATH}" @property def configured(self) -> bool: return bool(self.api_key) @property def headers(self) -> Dict[str, str]: if not self.api_key: raise APIError(_missing_key_message()) return { "Authorization": f"Bearer {self.api_key}", "Content-Type": "application/json", } def _post(self, payload: Dict[str, Any], stream: bool = False, timeout: int = 120) -> requests.Response: try: response = requests.post( self.api_url, headers=self.headers, json=payload, stream=stream, timeout=timeout, ) ``` ### Technical Analysis The script accepts `SENSEAUDIO_API_BASE` without validating its scheme or hostname. It then constructs the request URL from that value and sends an `Authorization: Bearer` header containing `SENSEAUDIO_API_KEY`. For synthesis operations, the JSON request body also includes the complete user-provided text and synthesis parameters. Consequently, a modified environment or untrusted runtime configuration can redirect authentication and synthesis requests to an attacker-controlled endpoint. Sending the API key and user text to the default official SenseAudio endpoint is necessary for the declared remote TTS functionality. Allowing those values to be sent to an arbitrary endpoint is not necessary and vio ...[truncated 1188 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove `SENSEAUDIO_API_BASE` configurability if alternate endpoints are not required. 2. If configurability is required, parse the URL before sending any request and enforce: - The `https` scheme. - The exact approved hostname `api.senseaudio.cn`. - An expected or empty port. - Rejection of embedded credentials, fragments, and unexpected path components. 3. Construct the final endpoint from a fixed trusted origin and fixed API path rather than concatenating unrestricted strings. 4. Disable or carefully validate redirects so an approved endpoint cannot redirect a credential-bearing request to another host. 5. Never forward the `Authorization` header across a cross-origin redirect. 6. Document any supported alternate official endpoints and maintain an explicit allowlist. 7. Add tests confirming rejection of HTTP URLs, lookalike domains, localhost addresses, IP literals, user-info URL components, and unapproved ports. ]]>

T08 · Insecure Dependencies

Warning
Location
scripts/main.py:24
Finding
Automatic Installation of an Unpinned Runtime Dependency<![CDATA[ ## Vulnerability Details **File Location**: `scripts/main.py`, lines 24-50 **Vulnerability Type**: Unsafe runtime dependency installation **Risk Level**: Medium ### Vulnerable Code ```python def ensure_python_package(import_name: str, pip_name: Optional[str] = None) -> None: pip_name = pip_name or import_name try: importlib.import_module(import_name) return except ImportError: print(f"缺少 {pip_name},正在自动安装...", file=sys.stderr) result = subprocess.run( [sys.executable, "-m", "pip", "install", pip_name], text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) if result.returncode != 0: raise RuntimeError( f"自动安装 {pip_name} 失败,请手动执行: {sys.executable} -m pip install {pip_name}\n" f"stderr:\n{result.stderr.strip()}" ) try: importlib.import_module(import_name) except ImportError as exc: raise RuntimeError(f"已安装 {pip_name},但仍无法导入 {import_name}。") from exc ensure_python_package("requests") import requests ``` ### Technical Analysis When `requests` is unavailable, the script automatically executes: ```bash python -m pip install requests ``` The package has no pinned version or integrity hash. Resolution therefore depends on the active pip configuration, configured package index, network state, and the latest package version available at execution time. This modifies the Python environment merely by starting the script, including commands such as `list-voices` that do not need network access. The behavior is also not disclosed in `SKILL.md`. Although the dependency name is a fixed legitimate package name rather than user input, an untrusted package index, compromised upstream release, or altered pip configuration can cause unreviewed code to be installed and subsequently imported. ### Attack Path 1. The runtime environment does not already contain the `requests` module. 2. An attacker compromises or con ...[truncated 1093 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove automatic `pip install` behavior from application startup. 2. Declare `requests` as an explicit project dependency and install it during a controlled deployment or setup phase. 3. Pin the dependency to a reviewed version in a lock file. 4. Use cryptographic hashes, such as pip's `--require-hashes`, to verify downloaded artifacts. 5. Install dependencies in an isolated virtual environment with a trusted, explicitly configured package index. 6. Fail safely with a clear installation instruction when the dependency is missing instead of modifying the environment automatically. 7. Document the dependency and setup requirements in `SKILL.md`. 8. Consider replacing `requests` with Python standard-library HTTPS functionality if doing so can meet the requirements without introducing equivalent security or maintenance risks. ]]>
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
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (12)

Ae1

High
Category
analysis-evasion
Content
本 Skill 的脚本位于 `SKILL.md` 同级的 `scripts/` 目录中。
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
本 Skill 的脚本位于 `SKILL.md` 同级的 `scripts/` 目录中。
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
if [ -f "./SKILL.md" ] && [ -f "./scripts/main.py" ] && grep -q "senseaudio-tts" "./SKILL.md"; then
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
if [ -f "./SKILL.md" ] && [ -f "./scripts/main.py" ] && grep -q "senseaudio-tts" "./SKILL.md"; then
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Lp3

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding
The skill performs sensitive operations—reading environment variables, invoking shell commands, making network requests, and writing files—but does not declare an explicit tool/permission scope. This increases the chance that an agent runtime grants broader capabilities than users expect, weakening least-privilege controls and making misuse or prompt-induced overreach more likely.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
The manifest description says the skill should trigger when the user says several Chinese phrases, and the rest of the document is written as Chinese operational guidance. This imposes a language-specific interaction pattern without any opt-in, multilingual alternative, or explanation that the skill is intentionally limited to a Chinese-only compliance or regional context.

External Transmission

Medium
Category
Data Exfiltration
Content
本 Skill 默认基于以下官方能力:

- 接口地址:`POST https://api.senseaudio.cn/v1/t2a_v2`
- 鉴权方式:`Authorization: Bearer API_KEY`
- 模型:`senseaudio-tts-1.5-260319`
- 支持文本最大长度:`10000` 字符
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Context-Inappropriate Capability

Medium
Confidence
97% confidence
Finding
A text-to-speech CLI should not need to modify the host environment by installing Python packages during execution. This behavior creates supply-chain risk, breaks reproducibility, and may execute attacker-controlled or tampered package code if the package source or environment is compromised.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The skill runs pip automatically without explicit user approval at the moment of execution. Silent dependency installation can surprise operators, bypass change-control expectations, and cause arbitrary third-party code to be fetched and executed on systems where the skill is merely expected to synthesize audio.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
except ImportError:
        print(f"缺少 {pip_name},正在自动安装...", file=sys.stderr)

    result = subprocess.run(
        [sys.executable, "-m", "pip", "install", pip_name],
        text=True,
        stdout=subprocess.PIPE,
Confidence
94% confidence
Finding
The code invokes pip at runtime to install a package automatically when imports fail. Although the subprocess call is not shell-injected here, it still enables unreviewed code retrieval and execution from package indexes during normal skill operation, which expands the attack surface and can lead to supply-chain compromise or unexpected environment mutation.

External Transmission

Medium
Category
Data Exfiltration
Content
def _post(self, payload: Dict[str, Any], stream: bool = False, timeout: int = 120) -> requests.Response:
        try:
            response = requests.post(
                self.api_url,
                headers=self.headers,
                json=payload,
Confidence
80% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Natural-Language Policy Violations

Low
Confidence
82% confidence
Finding
The module docstring and user-facing help text are presented in Chinese only, which effectively forces a specific language for interaction without indicating user choice or opt-in. This can violate language or locale policy where tools are expected to be language-neutral or offer alternatives.

Static analysis

No suspicious patterns detected.