Back to skill

Security audit

liber-speechapi

Security checks for vulnerabilities and agentic risk

Overview

The skill performs the advertised speech tasks, but its credential handling and download behavior create real risks that users should review before installing.

Install only if you trust the configured Liber SpeechAPI backend and understand that audio, text, and optional voice-clone samples may be sent to it. Prefer HTTPS, avoid using the bundled .env as production configuration, store only Liber-specific keys where this skill can read them, and review or patch the audio download origin check before using real credentials.

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 (3)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/liber_speech_client.py:37
Finding

Overbroad Loading of Secrets from the Shared OpenClaw Environment File

Content
View full analysis
None: if not dotenv_path.exists(): return for raw_line in dotenv_path.read_text(encoding="utf-8").splitlines(): line = raw_line.strip() if not line or line.startswith("#") or "=" not in line: continue key, value = line.split("=", 1) key = key.strip() value = value.strip().strip('"').strip("'") os.environ.setdefault(key, value) ``` The function is applied to the shared OpenClaw credential file: ```python # If not found in environment variables, try loading from ~/.openclaw/.env if not base_url or not api_key: openclaw_env_path = Path.home() / ".openclaw" / ".env" load_dotenv(openclaw_env_path) base_url = os.getenv("LIBER_API_BASE_URL", "").strip().rstrip("/") api_key = os.getenv("LIBER_API_KEY", "").strip() ``` ### Technical Analysis The Skill only requires `LIBER_API_BASE_URL` and `LIBER_API_KEY`. However, `load_dotenv()` reads every assignment in `~/.openclaw/.env` and inserts every parsed value into the process environment. A shared OpenClaw environment file may contain credentials for unrelated services. Importing all of those values violates least privilege because the Skill does not need them for ASR or TTS operations. It also unnecessarily exposes the values to every module running in the same Python process. The reviewed code does not deliberately transmit unrelated environment variables. Nevertheless, the expanded credential scope increases the effect of a compromised dependency, future code defect, diagnostic routine, or other code executing in the process. ### Attack Path 1. A user stores Liber credentials and unrelated service credent ...[truncated 890 chars]
Remediation
View remediation
dict[str, str]: allowed = {"LIBER_API_BASE_URL", "LIBER_API_KEY"} result: dict[str, str] = {} if not path.is_file(): return result for raw_line in path.read_text(encoding="utf-8").splitlines(): line = raw_line.strip() if not line or line.startswith("#") or "=" not in line: continue key, value = line.split("=", 1) key = key.strip() if key in allowed: result[key] = value.strip().strip('"').strip("'") return result ``` 2. Return credentials as local values rather than writing them to `os.environ`. 3. Prefer a dedicated Skill-specific credential file over a shared global environment file. 4. Validate that credential files are regular files and, where supported, reject files with overly permissive filesystem permissions. 5. Document precisely which keys are read and why they are required. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/liber_speech_client.py:260
Finding

API Bearer Token Forwarded to Server-Controlled Cross-Origin Download URL

Content
View full analysis
``` Consequently, a malicious or compromised SpeechAPI server can direct the client to an attacker-controlled origin and cause the API credential to be disclosed. The same issue may arise through HTTP redirects because Requests follows redirects by default and the implementation does not explicitly validate the final origin. The broad `startswith("http")` check is also not a sufficient URL-scheme validator. URL parsing and an explicit origin policy are ...[truncated 1450 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
.env:2
Finding

Bearer Credential and Speech Data Transmitted over Plaintext HTTP

Content
View full analysis
dict[str, str]: return {"Authorization": f"Bearer {api_key}"} ``` ### Technical Analysis The bundled active `.env` file configures a bearer-authenticated endpoint using plaintext HTTP. ASR requests upload audio recordings, TTS requests transmit text and optional voice-cloning samples, and download requests retrieve generated audio. Without TLS, these credentials and data are not protected against network interception or modification. The configured hostname, `local-test`, is not intrinsically guaranteed to resolve to a loopback address. It may be resolved through DNS, a hosts-file entry, a container network, or another network namespace. Therefore, the configuration cannot safely assume that all traffic remains on the local machine. The committed value `local_test_key` appears test-oriented, but its validity cannot be established from static review. Shipping an active `.env` file with any credential value also encourages insecure secret-management practices. ### Attack Path 1. The user runs the Skill with the bundled `.env` configuration or another HTTP API URL. 2. `local-test` resolves to a non-loopback address, or traffic traverses an untrusted local/container network. 3. The client submits the bearer token in an unencrypted HTTP header. 4. For ASR, the client also uploads the user's audio recording; for TTS, ...[truncated 752 chars]
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (23)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · references/config.md (reported line 12)May include surrounding context.

md
---

## 1. .env 文件(核心配置)

### 必填变量

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · references/config.md (reported line 21)May include surrounding context.

md
---

## 1. .env 文件(核心配置)

### 必填变量

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/liber_speech_client.py (reported line 126)May include surrounding context.

python
---

## 1. .env 文件(核心配置)

### 必填变量

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/liber_speech_client.py (reported line 133)May include surrounding context.

python
---

## 1. .env 文件(核心配置)

### 必填变量

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/liber_speech_client.py (reported line 143)May include surrounding context.

python
---

## 1. .env 文件(核心配置)

### 必填变量

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/liber_speech_client.py (reported line 145)May include surrounding context.

python
---

## 1. .env 文件(核心配置)

### 必填变量

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · references/config.md (reported line 171)May include surrounding context.

复制示例配置文件

bash
copy .env.example .env
copy config.json.example config.json

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/liber_speech_client.py (reported line 128)May include surrounding context.

python
# If not found in environment variables, try loading from ~/.openclaw/.env
    if not base_url or not api_key:
        openclaw_env_path = Path.home() / ".openclaw" / ".env"
        load_dotenv(openclaw_env_path)
        base_url = os.getenv("LIBER_API_BASE_URL", "").strip().rstrip("/")
        api_key = os.getenv("LIBER_API_KEY", "").strip()

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/liber_speech_client.py (reported line 135)May include surrounding context.

python
# If not found in environment variables, try loading from ~/.openclaw/.env
    if not base_url or not api_key:
        openclaw_env_path = Path.home() / ".openclaw" / ".env"
        load_dotenv(openclaw_env_path)
        base_url = os.getenv("LIBER_API_BASE_URL", "").strip().rstrip("/")
        api_key = os.getenv("LIBER_API_KEY", "").strip()

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The README documents HTTP/API usage and remote FastAPI deployment but does not clearly warn that user audio, transcriptions, and TTS text may be transmitted to a remote service. This creates a real privacy and compliance risk because operators or users may unknowingly send sensitive voice or text data over the network, especially when configured against non-local endpoints.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

This markdown file documents LIBER_API_KEY and hf_token as configuration values, but it does not warn users that these are sensitive secrets that should not be committed, shared, or stored insecurely. For markdown files, missing warnings about behaviors affecting privacy or credential safety should be flagged when the documentation could lead users to expose sensitive data.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The config examples set both ASR and TTS language to zh, and later parameter tables document zh as the default language for input and output. This is a natural-language locale policy concern because the file establishes a specific language default without explicit user opt-in or a documented region-specific justification.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

该 markdown 文档在示例配置中将 asr.language 和 tts.language 默认设为 zh,后文多个场景示例也持续固定为中文。根据规则,强制特定语言而未提供用户选择或明确的区域/业务正当性,属于自然语言层面的语言/地区政策风险。

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The workflow explicitly sends user-provided audio and derived transcript content to external ASR/TTS services, but it does not mention consent, disclosure, retention limits, or handling of sensitive data. Because voice and transcript content may contain personal or confidential information, this creates a real privacy and data-governance risk, especially in a Telegram integration where users may assume they are only interacting with the bot platform.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The instruction to summarize replies 'to within 100 Chinese characters' enforces a specific language/locale behavior in natural-language guidance. The file does not state that this is optional, user-selected, or limited to a justified Chinese-language deployment context.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The default configuration sets both asr.language and tts.language to zh, which imposes a specific language behavior even when the user does not request it. Under the policy, forcing a language or locale without explicit user choice is a natural-language policy violation unless clearly justified or opt-in.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The code writes downloaded audio to disk either in a default results directory or at a user-specified output path without warning about file creation or overwrite behavior. This can lead to unintended persistence of potentially sensitive generated audio, and a caller may accidentally overwrite files if an existing path is supplied.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The client sends user-provided audio and text to a remote API endpoint for ASR/TTS, but this file provides no user-facing disclosure or confirmation at the point of transmission. In a skill context, this can expose sensitive voice content or text to a third-party service unexpectedly, creating a real privacy and data-handling risk even if the network behavior is functionally intended.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The config hard-codes "language": "zh" for both speech recognition and text-to-speech. This is a natural-language policy concern because it enforces a specific language/locale without any indication that users can select another language or opt in to this restriction.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
76% confidence
Finding

该 README 全文以中文撰写并以中文示例作为默认交互展示,但未明确说明这是文档语言选择而非技能输出语言强制要求。结合政策要求,若技能面向通用用户而默认仅提供单一语言体验、又没有清晰的语言选择或 opt-in 说明,可能构成语言/locale 方面的自然语言策略风险。

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
80% confidence
Finding

文档一方面说明模型类型可为 multilingual,另一方面又把 language 默认固定为 zh,且未提示用户应按目标语言显式选择。这会在自然语言说明层面造成默认中文输出的隐含约束,不符合应提供语言选择或明确适用范围的要求。

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
96% confidence
Finding

The dependency is specified with a lower bound only (requests>=2.31.0), which makes builds non-reproducible and allows installation of different versions over time. This becomes a security issue because a vulnerable or behavior-changing release could be pulled in later without review, and the current manifest provides no assurance about what version is actually used.

Content

Scanner excerpt · requirements.txt (reported line 1)May include surrounding context.

text
requests>=2.31.0

Unverifiable Dependency: requests has 16 known advisory(ies) (CVE-2014-1830 (Exposure of Sensitive Information to an Unauthorized Actor in Requests); CVE-2024-47081 (Requests vulnerable to .netrc credentials leak via malicious URLs); CVE-2024-35195 (Requests `Session` object does not verify requests after making first request wi) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
91% confidence
Finding

The manifest references requests without pinning an exact version, while the package has multiple known advisories across versions. Because the resolved version is unknown, you cannot verify whether deployment will include a vulnerable release, which weakens supply-chain assurance and may expose the skill to known dependency flaws depending on install time.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.