Back to skill

Security audit

Fish Audio S2 Pro TTS

Security checks for vulnerabilities and agentic risk

Overview

This TTS skill is mostly coherent documentation, but it asks users to run exposed voice-cloning services and mutable installs without enough scoping or safety guidance.

Review this skill before installing. Prefer loopback-only services, pin package/model/container versions or digests, avoid arbitrary URL and file:// reference audio, and only use voice cloning with explicit permission from the speaker. Treat uploaded voice samples as sensitive biometric data and confirm how they are retained or deleted.

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

Warning
Location
SKILL.md:48
Finding
API Server Binds to All Network Interfaces Without Documented Access Controls<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 48-51 **Vulnerability Type**: Externally reachable service with insufficiently documented access controls **Risk Level**: Medium ### Vulnerable Code ```bash **Native API Server:** ```bash python tools/api_server.py --llama-checkpoint-path checkpoints/s2-pro --decoder-checkpoint-path checkpoints/s2-pro/codec.pth --listen 0.0.0.0:8080 ``` ``` ### Technical Analysis The deployment command binds the native API server to `0.0.0.0`, making it reachable through every available network interface rather than limiting it to the local host. The Skill does not instruct the operator to enable authentication, authorization, TLS, request throttling, or network filtering. The documented API includes speech generation and voice-management operations. In particular, `references/api-reference.md` documents voice-sample upload, deletion, and persistent storage under `~/.cache/vllm-omni/speakers/`. If the native server exposes these operations without additional access controls, an unauthenticated network client could invoke sensitive or resource-intensive functionality. Binding to every interface is not required for the minimum declared local TTS functionality. A loopback binding would be sufficient for the examples that send requests to `localhost`. ### Attack Path 1. An operator starts the server using the documented command. 2. The process listens on port 8080 across all network interfaces. 3. An attacker with network access to the host discovers the exposed service. 4. The attacker submits repeated synthesis requests to consume GPU, CPU, and memory resources. 5. If the documented voice-management endpoints are available without authorization, the attacker uploads unauthorized voice samples or modifies/deletes stored voice profiles. 6. Generated output or stored biometric voice data may consequently be exposed to unauthorized parties, depending on the server implementation and surrounding infrastruct ...[truncated 697 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Bind to the loopback interface by default: ```bash python tools/api_server.py \ --llama-checkpoint-path checkpoints/s2-pro \ --decoder-checkpoint-path checkpoints/s2-pro/codec.pth \ --listen 127.0.0.1:8080 ``` 2. If remote access is necessary, place the service behind an authenticated reverse proxy and require TLS. 3. Enforce authorization separately for synthesis, voice upload, voice deletion, and voice enumeration. 4. Configure host and network firewalls so only explicitly trusted clients can reach the service. 5. Add request-size, batch-size, concurrency, generation-token, and rate limits. 6. Avoid logging request text, transcripts, reference audio, authentication headers, or generated biometric data. 7. Document retention and deletion controls for stored voice profiles. 8. Clearly warn operators that binding to `0.0.0.0` creates network exposure and should be an explicit opt-in configuration. ]]>

T08 · Insecure Dependencies

Warning
Location
SKILL.md:19
Finding
Installation Instructions Retrieve Unpinned Executable Dependencies and Model Artifacts<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 19-26 **Vulnerability Type**: Mutable and unverified third-party dependencies **Risk Level**: Medium ### Vulnerable Code ```bash conda create -n fish-speech python=3.12 && conda activate fish-speech pip install -e .[cu129] # CUDA 12.9 # or: uv sync --python 3.12 --extra cu129 # minimal: pip install fish-speech apt install portaudio19-dev libsox-dev ffmpeg # System dependencies hf download fishaudio/s2-pro --local-dir checkpoints/s2-pro ``` Related mutable installation instructions also appear in `references/install.md`, including: ```bash pip install fish-speech pip install --pre torch torchvision torchaudio --index-url https://download.pytorch.org/whl/nightly/xpu docker pull fishaudio/fish-speech ``` ### Technical Analysis The Skill directs users to retrieve and install executable packages, container images, and model artifacts without immutable version identifiers, cryptographic hashes, or container digests. `pip install fish-speech` resolves whatever version the package index currently serves. The nightly PyTorch instruction is especially mutable because pre-release builds change continuously. Likewise, `docker pull fishaudio/fish-speech` retrieves a mutable image tag, and `hf download fishaudio/s2-pro` does not specify a reviewed commit revision. Python installation can execute package build hooks and installed application code. Container images can contain arbitrary executables and startup behavior. Model repositories may also include configuration or auxiliary files consumed by external frameworks. Consequently, the effective behavior installed by these instructions can change after the Skill itself has been reviewed. This is necessary supply-chain access for installing the declared TTS system, but the unrestricted and unpinned form exceeds the minimum trust required. ### Attack Path 1. An attacker compromises an upstream package, publisher account, image registry acco ...[truncated 1480 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin every Python dependency to an exact reviewed version. 2. Use a lockfile containing cryptographic hashes and install with hash verification, such as `pip --require-hashes`. 3. Avoid nightly or pre-release dependencies in production guidance. If unavoidable, pin an exact build and verify its hash. 4. Pin Docker images by immutable digest: ```bash docker pull fishaudio/fish-speech@sha256:<reviewed-digest> ``` 5. Pin Hugging Face downloads to a reviewed commit revision and verify expected file checksums: ```bash hf download fishaudio/s2-pro \ --revision <reviewed-commit> \ --local-dir checkpoints/s2-pro ``` 6. Publish a software bill of materials covering packages, images, and downloaded model artifacts. 7. Verify package publisher identities and use trusted package indexes with explicit index configuration. 8. Perform installation in an isolated, non-privileged environment without access to secrets or unrelated user files. 9. Run containers as a non-root user with read-only filesystems, minimal mounts, dropped Linux capabilities, and restricted outbound networking. 10. Document the exact package versions, image digests, model revisions, and checksums that were security-reviewed. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (12)

External Transmission

Medium
Category
Data Exfiltration
Content
## API Calls

### cURL

```bash
# Basic TTS
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The skill explicitly documents voice-cloning behavior but provides no warning about consent, impersonation, or privacy risks. In a TTS skill, this materially increases misuse risk because users are guided to submit reference audio and generate cloned speech without any guardrails or policy cues.

External Transmission

Medium
Category
Data Exfiltration
Content
-d '{"input": "Streaming.", "stream": true, "response_format": "pcm"}' --no-buffer | play -t raw -r 44100 -e signed -b 16 -c 1 -

# Batch
curl -X POST http://localhost:8091/v1/audio/speech/batch \
  -H "Content-Type: application/json" \
  -d '{"items": [{"input": "Sentence 1"}, {"input": "Sentence 2"}], "voice": "default"}'
```
Confidence
60% 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
```python
import requests
resp = requests.post("http://localhost:8091/v1/audio/speech", json={
    "input": "Hello.", "voice": "default",
    "ref_audio": "https://...", "ref_text": "Reference text"
})
Confidence
60% 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
```python
import requests
resp = requests.post("http://localhost:8091/v1/audio/speech", json={
    "input": "Hello.", "voice": "default",
    "ref_audio": "https://...", "ref_text": "Reference text"
})
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Internal Network Request

Medium
Category
Server-Side Request Forgery
Content
```python
import requests
resp = requests.post("http://localhost:8091/v1/audio/speech", json={
    "input": "Hello.", "voice": "default",
    "ref_audio": "https://...", "ref_text": "Reference text"
})
Confidence
70% confidence
Finding
Code issues a request to a loopback, link-local, or private-range host. This can reach internal services not meant to be exposed and is a common SSRF pivot.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
Allowing ref_audio to come from URL, base64, or file:// sources without warning or restriction creates privacy and local file access risk. If an implementation follows this interface naively, it may fetch attacker-controlled URLs or read local files, leading to SSRF, sensitive file exposure, or processing of private data without user awareness.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
This markdown file documents uploading a voice sample and deleting a voice, including that uploaded data is persisted under the user's cache directory, but it does not provide any explicit warning about privacy implications, persistence, or the destructive nature of deletion. For markdown files, operations affecting user data or system state should include clear user-facing warnings.

External Transmission

Medium
Category
Data Exfiltration
Content
**Upload:**
```bash
curl -X POST http://localhost:8091/v1/audio/voices \
  -F "audio_sample=@voice.wav" -F "consent=user_id" \
  -F "name=my_voice" -F "ref_text=Transcript." -F "speaker_description=warm narrator"
```
Confidence
60% 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
```python
import requests, json, base64, io, wave

with requests.post(..., json={..., "stream": True}, stream=True) as s:
    chunks, fmt = [], None
    for line in s.iter_lines(decode_unicode=True):
        if not line or not line.startswith("data: ") or "[DONE]" in line: continue
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Rp1

Medium
Category
MCP Rug Pull
Confidence
92% confidence
Finding
The installation guide instructs users to pull a Docker image without pinning a specific tag or immutable digest, so the content retrieved can change over time. This creates a supply-chain risk: if the publisher account is compromised or the latest image is replaced with a malicious or broken build, users may run unreviewed code.

Rp1

Medium
Category
MCP Rug Pull
Confidence
78% confidence
Finding
This `docker run` example executes the same unpinned image reference, which may resolve to whatever local or remote image currently matches `fish-speech:webui`. If users build or pull a different image under that tag, the command can run unexpected code with GPU access and mounted host directories, increasing supply-chain and host exposure risks.

Static analysis

No suspicious patterns detected.