Back to skill

Security audit

Bailian TTS

Security checks for vulnerabilities and agentic risk

Overview

This is a straightforward Alibaba Bailian/DashScope text-to-speech helper with normal cloud API risks and some hardening gaps, but no hidden or destructive behavior.

Install in an isolated environment, pin dependency versions where possible, protect the DashScope API key, avoid submitting secrets or regulated personal data to the cloud TTS service, and treat output paths carefully because the script writes the downloaded audio to the path you choose.

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
SKILL.md:138
Finding
Unpinned Third-Party Dependencies<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:138` **Vulnerability Type**: Unpinned dependency installation **Risk Level**: Medium ### Vulnerable Code ```bash pip3 install dashscope requests ``` ### Technical Analysis The documented installation command installs `dashscope` and `requests` without fixed versions or package hashes. Consequently, the code installed by users can change over time without any corresponding change to the reviewed project. If a dependency, transitive dependency, package index, or future package release is compromised, following this command could install and execute attacker-controlled code. Python packages may execute code during installation and whenever they are imported. Both dependencies are imported directly by `scripts/tts.py`. This finding concerns unsafe dependency management. The audit found no evidence that either named package is currently malicious, misspelled, or intentionally sourced from an untrusted repository. ### Attack Path 1. An attacker compromises a listed dependency, one of its transitive dependencies, or the package repository used by `pip`. 2. The attacker publishes a malicious version that still satisfies the unconstrained installation command. 3. A user follows the documented `pip3 install dashscope requests` command. 4. The malicious package executes code during installation or when `scripts/tts.py` imports it. 5. The code runs with the operating-system privileges of the user performing the installation or invoking the script. ### Impact Assessment Successful exploitation could permit arbitrary code execution with the privileges of the installing or invoking user. Depending on those privileges, an attacker could access user-readable files and environment variables, including `DASHSCOPE_API_KEY`, modify files, make network requests, or compromise the Python environment. This issue does not independently provide privilege escalation beyond the affected user's existing permissions. ...[truncated 4 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin every direct and transitive dependency to a reviewed version in a requirements or lock file. 2. Generate and verify cryptographic hashes, for example by using `pip install --require-hashes -r requirements.txt`. 3. Install packages from an explicitly configured, trusted package index. 4. Review dependency release notes and security advisories before updating pins. 5. Use an isolated virtual environment with only the permissions needed for TTS generation. 6. Add automated dependency vulnerability and integrity scanning to the release process. Example hardened installation approach: ```bash python3 -m pip install --require-hashes -r requirements.txt ``` The corresponding `requirements.txt` should contain exact versions and SHA-256 hashes for direct and transitive dependencies. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/tts.py:89
Finding
Unvalidated API-Provided Audio Download URL<![CDATA[ ## Vulnerability Details **File Location**: `scripts/tts.py:89-97` **Vulnerability Type**: Unrestricted remote URL fetch and redirect handling **Risk Level**: Medium ### Vulnerable Code ```python if 'audio' in output and 'url' in output['audio']: audio_url = output['audio']['url'] # 下载音频 audio_response = requests.get(audio_url, timeout=60) if audio_response.status_code == 200: with open(output_file, "wb") as f: f.write(audio_response.content) ``` ### Technical Analysis The script takes `output['audio']['url']` from the remote API response and passes it directly to `requests.get`. It does not validate: - The URL scheme. - The destination hostname. - Whether DNS resolves to a loopback, private, link-local, or otherwise sensitive address. - Redirect destinations; `requests` follows redirects by default. - The response content type. - The maximum response size. This creates a server-side request forgery-style request primitive if an attacker can influence the API response or redirect chain. The request originates from the machine running the Skill and therefore has access to network destinations reachable from that machine. A successful response is also loaded into memory in full and written to the user-selected output path without confirming that it is audio data. Under normal operation, the URL is supplied by the configured Aliyun API. Exploitation therefore requires compromise or manipulation of that response, a hostile redirect, or equivalent control over the returned URL. The reviewed code does not itself demonstrate that Aliyun returns hostile URLs. ### Attack Path 1. An attacker compromises or otherwise gains influence over the API response or a server in the returned redirect chain. 2. The attacker places an arbitrary URL in `output.audio.url`, or causes an initially permitted URL to redirect to a sensitive destination. 3. The script calls `requests.get` without validating the original or redirect ...[truncated 1095 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Parse the returned URL before making the request and permit only HTTPS. 2. Maintain an allowlist of documented Aliyun audio-storage hostnames rather than accepting arbitrary hosts. 3. Resolve the hostname and reject loopback, private, link-local, multicast, reserved, and unspecified IP address ranges for both IPv4 and IPv6. 4. Disable automatic redirects with `allow_redirects=False`, or validate every redirect destination using the same scheme, hostname, and IP-address rules. 5. Stream the response and enforce a conservative maximum download size. 6. Validate the response `Content-Type` against expected audio formats before writing it. 7. Write to a securely created temporary file and atomically move it into place only after all checks succeed. 8. Avoid exposing detailed internal response contents in error messages. A hardened request should follow this general pattern: ```python audio_response = requests.get( validated_audio_url, timeout=(5, 60), allow_redirects=False, stream=True, ) audio_response.raise_for_status() ``` Before this request, `validated_audio_url` should be checked against an explicit HTTPS hostname allowlist and prohibited IP ranges. If redirects are required by the service, each `Location` value must be independently validated before it is followed. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (3)

Tainted flow: 'audio_url' from os.getenv (line 90, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Content
audio_url = output['audio']['url']
                    
                    # 下载音频
                    audio_response = requests.get(audio_url, timeout=60)
                    if audio_response.status_code == 200:
                        with open(output_file, "wb") as f:
                            f.write(audio_response.content)
Confidence
91% confidence
Finding
The script blindly trusts an audio URL returned by an external API and fetches it with requests.get without validating the scheme, host, or destination. If the upstream service is compromised or returns attacker-controlled URLs, this can enable server-side request forgery behavior or unintended network access from the host running the skill, and the fetched content is then written directly to a user-chosen file path.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill documents a cloud-based TTS service and even mentions API key configuration, but it does not clearly warn users that submitted text and, for voice-cloning features, optional audio samples may be sent to a third-party provider. This can lead users to unknowingly transmit sensitive or regulated data off-platform, creating privacy, compliance, and data-handling risks.

Natural-Language Policy Violations

Medium
Confidence
88% confidence
Finding
This code file contains user-facing natural-language descriptions and CLI help text that assume Chinese as the only interaction language. Under the policy, forcing a specific language without user opt-in can be a locale/language policy violation unless the restriction is explicitly justified.

Static analysis

No suspicious patterns detected.