Back to skill

Security audit

Multi Edge Tts Cn

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent Chinese Edge-TTS audio generator, but its output path checks do not enforce the documented whitelist and can overwrite arbitrary writable files.

Review this before installing. Use only trusted text and explicit output paths under /tmp/openclaw or the documented OpenClaw media/workspace directories, and avoid running the installer in a privileged or system Python environment. The package is not judged malicious, but the arbitrary writable output path and unpinned dependency install should be fixed before routine use.

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)

T08 · Insecure Dependencies

Warning
Location
scripts/install.sh:32
Finding
Unpinned Dependency Installation into the System Python Environment<![CDATA[ ## Vulnerability Details **File Location**: `scripts/install.sh`, lines 32-34 **Vulnerability Type**: Unpinned third-party dependency installation **Risk Level**: Medium ### Vulnerable Code ```bash pip3 install --break-system-packages edge-tts 2>/dev/null || \ pip3 install --user edge-tts 2>/dev/null || \ pip3 install edge-tts 2>/dev/null ``` ### Technical Analysis The installation script downloads `edge-tts` without specifying the documented version or verifying the integrity of the downloaded artifacts. Although `SKILL.md` identifies version `7.2.8`, the installer resolves whichever release is current when installation occurs. The first installation attempt also uses `--break-system-packages`, bypassing Python protections intended to prevent `pip` from modifying an externally managed system environment. This can overwrite distribution-managed packages or create incompatible dependency combinations. This is a supply-chain risk rather than evidence that the current `edge-tts` package is malicious. Exploitation would require compromise of the package, its distribution account, the configured package index, or the dependency resolution path. ### Attack Path 1. An attacker compromises the package distribution account, package index, or another dependency resolved during installation. 2. The attacker publishes a malicious or altered release that satisfies the unrestricted package request. 3. A user executes `scripts/install.sh`. 4. `pip3` retrieves the mutable package release and executes its installation process. 5. Malicious installation or runtime code executes with the privileges of the user running the script. 6. If the installer is run by an administrator, or against a privileged Python environment, the impact extends to that privileged environment. ### Impact Assessment Successful supply-chain exploitation could allow arbitrary code execution under the invoking user's account, access to that user's files and environment variables, and m ...[truncated 355 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin the documented dependency version: ```bash python3 -m pip install "edge-tts==7.2.8" ``` 2. Install dependencies in a dedicated virtual environment rather than modifying the system Python environment: ```bash python3 -m venv "$SKILL_DIR/.venv" "$SKILL_DIR/.venv/bin/python" -m pip install --require-hashes -r requirements.txt ``` 3. Create a locked requirements file containing exact versions and cryptographic hashes for all transitive dependencies. 4. Use `python -m pip` with the selected interpreter instead of invoking a potentially unrelated `pip3` executable. 5. Remove `--break-system-packages`. If system-wide installation is genuinely required, document it as a separate, explicit administrative operation. 6. Do not suppress all installation error output. Preserve diagnostic information so package source and integrity failures can be investigated. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/engine.py:111
Finding
Ineffective Output-Path Allowlist Permits Arbitrary Writable File Overwrite<![CDATA[ ## Vulnerability Details **File Location**: `scripts/engine.py`, lines 111-124 **Vulnerability Type**: Improper path validation and unrestricted file overwrite **Risk Level**: High ### Vulnerable Code The allowlist check accepts matching string prefixes: ```python abs_path = os.path.abspath(output_path) for allowed in allowed_dirs: if abs_path.startswith(os.path.abspath(allowed)): return True ``` Disallowed paths are also accepted unconditionally: ```python return True ``` The return value is not enforced before the destination is passed to the conversion operation, which uses `ffmpeg -y` and therefore permits replacement of an existing destination file. ### Technical Analysis The validation function fails closed in neither of its relevant cases: 1. A path outside every allowed directory still produces `True`. 2. Directory membership is checked with `str.startswith()`, which is not a path-aware containment operation. For example, `/tmp/openclaw-evil/file.ogg` has the permitted string prefix `/tmp/openclaw` but is not inside `/tmp/openclaw`. The caller invokes `validate_output_path(output_path)` without checking its result. The conversion function then creates the destination parent directory and runs `ffmpeg` with `-y`, which overwrites an existing destination without confirmation. Because the output path is exposed through the `--output` CLI argument and the `generate()` API, any caller able to influence that parameter can direct generated audio to an arbitrary filesystem location writable by the process. Path canonicalization also does not protect against symlink-based redirection. `os.path.abspath()` normalizes the textual path but does not resolve filesystem symlinks. A symlink placed under an allowed directory could therefore target a file elsewhere. ### Attack Path 1. An attacker or untrusted workflow supplies a crafted `--output` value to `engine.py`. 2. The value identifies a sensitive file writable by the invoking ...[truncated 1204 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Reject paths outside the allowlist instead of returning success after a warning. 2. Resolve both the destination and allowed directories to canonical paths and perform path-aware containment checks: ```python def validate_output_path(output_path: str) -> bool: destination = Path(output_path).expanduser().resolve(strict=False) allowed_dirs = [ Path("/tmp/openclaw").resolve(), Path("~/.openclaw/media").expanduser().resolve(), Path("~/.openclaw/workspace").expanduser().resolve(), Path("~/.openclaw/sandboxes").expanduser().resolve(), ] return any(destination.is_relative_to(base) for base in allowed_dirs) ``` 3. Enforce the result in `generate()`: ```python if not validate_output_path(output_path): return 1, "" ``` 4. Reject existing symlink destinations and verify that each existing parent component does not redirect outside the approved directory. 5. Avoid blindly overwriting existing files. Generate a unique filename or use exclusive file creation unless replacement was explicitly requested by a trusted caller. 6. Revalidate the canonical destination immediately before writing to reduce time-of-check/time-of-use exposure. 7. Restrict destination extensions to the explicitly supported audio formats and apply conservative permissions to generated files and directories. ]]>
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • 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
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (9)

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill documentation describes capabilities that require network access, shell execution, and file reads, but it does not declare any explicit tool scope such as permissions or allowed-tools. This creates an authorization and review gap: an agent may invoke broader capabilities than a user or platform expects, increasing the risk of unintended command execution, external data transmission, or file access in a networked TTS workflow.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
The text specification states '使用中文标点' and defines pause behavior around Chinese punctuation, which imposes a specific language/locale convention. The file does not present this as an option or a region-specific requirement, so it reads as a forced locale policy in the skill guidance.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The module docstring, CLI help, and user-facing messages are written entirely in Chinese, which imposes a specific language on users and calling agents. Under the policy, locale or language constraints should either be optional/opt-in or clearly documented as a justified regional restriction, which is not stated here.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
return False
    
    # 检查 ffmpeg
    result = subprocess.run(
        ["ffmpeg", "-version"], 
        capture_output=True, 
        text=True
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Intent-Code Divergence

Medium
Confidence
99% confidence
Finding
`validate_output_path()` claims to validate writes to allowed directories, but it only prints a warning and still returns `True`, so callers can write output files anywhere the process has permission. In this skill context, the agent may accept externally influenced `output_path` values, enabling arbitrary file creation or overwrite in user-owned locations, which is more dangerous because the tool is explicitly designed to write files on demand.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
# AMR 格式需要 8kHz 采样率
    sample_rate = "8000" if ext == ".amr" else "48000"

    result = subprocess.run(
        [
            "ffmpeg", "-y", "-i", mp3_path,
            "-ar", sample_rate, "-ac", "1",
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
This shell script presents its instructions, status messages, and usage text entirely in Chinese, including the installation banner, errors, and final invocation guidance. That imposes a specific language on all users without opt-in, which matches the policy-violation category for language or locale constraints.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
ffmpeg_ver=$(ffmpeg -version 2>&1 | head -1)
    echo "✅ ffmpeg: $ffmpeg_ver"
else
    echo "❌ 需要 ffmpeg,请安装: sudo apt install ffmpeg"
    exit 1
fi
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Natural-Language Policy Violations

Low
Confidence
89% confidence
Finding
This manifest-style JSON defines only zh-CN, zh-HK, and zh-TW voices and uses a Chinese voice as the default, which indicates an effective language/locale constraint. Because the file provides no natural-language justification or indication that users can opt into this locale restriction, it may conflict with policy against forcing a specific language or locale.

Static analysis

No suspicious patterns detected.