Back to skill

Security audit

Voice Chat Skill

Security checks for vulnerabilities and agentic risk

Overview

The skill is a plausible voice-chat demo, but it needs review because it can send microphone audio or text to cloud services and includes unsafe shell-based example code without clear enough user consent and scoping.

Review this before installing or running. Use it only if you are comfortable with microphone audio or generated text being sent to third-party speech services, or choose a genuinely offline/simulated mode. Pin dependencies in a virtual environment, avoid administrator installs, and do not copy the shell=True TTS playback example into production code.

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

T08 · Insecure Dependencies

Warning
Location
SKILL.md:52
Finding
Unpinned Third-Party Dependencies Create a Supply-Chain Risk## Vulnerability Details **File Location**: `SKILL.md:52-57`; additional dependency instructions appear in `README.md:55-66` **Vulnerability Type**: Unpinned third-party package installation **Risk Level**: Medium ### Vulnerable Code ```bash pip install SpeechRecognition pyaudio pip install pipwin pipwin install pyaudio ``` ### Technical Analysis The installation instructions retrieve and install packages without specifying reviewed versions, package hashes, a lockfile, or an approved package index. The effective code installed by these commands can therefore change after the Skill has been audited. Python package installation can execute package build and installation logic under the privileges of the invoking user. If an upstream package, dependency, account, or package-index response is compromised, users following these instructions could install attacker-controlled code. No evidence indicates that the currently named packages are malicious. The vulnerability is the absence of dependency integrity and reproducibility controls. ### Attack Path 1. An attacker compromises a listed package, one of its transitive dependencies, or its package-index distribution channel. 2. The attacker publishes a malicious release under a version accepted by the unpinned installation command. 3. A user follows the documented installation instructions. 4. `pip` resolves the malicious release because no version or hash restrictions are present. 5. Malicious build or package code executes with the installing user's privileges. 6. The installed package can execute again when imported by the voice-chat scripts. ### Impact Assessment Successful exploitation can provide arbitrary code execution with the privileges of the user running `pip` or launching the application. Depending on those privileges, an attacker could access user files, environment variables, microphone data, network resources, and credentials available to that accou ...[truncated 113 chars]
Remediation
## Remediation Suggestions - Pin every direct dependency to a reviewed version. - Generate a lockfile that also fixes transitive dependency versions. - Require package hashes, for example through a requirements file used with `pip --require-hashes`. - Install dependencies in a dedicated virtual environment with ordinary user privileges. - Use an explicitly configured, trusted package index. - Review package provenance and release signatures where available. - Add automated dependency vulnerability and integrity scanning. - Replace the installation instructions with a reproducible command such as: ```bash python -m pip install --require-hashes -r requirements.txt ```

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:114
Finding
Shell Invocation with a Caller-Controlled Output Filename## Vulnerability Details **File Location**: `SKILL.md:114-140` **Vulnerability Type**: Potential OS command injection **Risk Level**: High ### Vulnerable Code ```python def openclaw_tts(text, output_file="output.mp3"): result = subprocess.run([ "node", "path/to/openclaw/tts-tool.js", "--input", request_file, "--output", output_file ], capture_output=True, text=True) if result.returncode == 0: subprocess.run(["start", output_file], shell=True) ``` ### Technical Analysis The documented function accepts `output_file` from its caller and later invokes a command through the operating-system shell with `shell=True`. Shell execution changes the trust boundary: shell metacharacters contained in a filename may be interpreted as command syntax rather than as literal filename characters. Passing arguments as a list does not provide a reliable security boundary when shell execution is enabled, particularly when invoking a shell built-in such as `start`. If an integration derives `output_file` from user input, model output, message metadata, or another untrusted source, an attacker may be able to append additional shell commands. The project’s executable `voice_chat.py` does not currently call this documented shell-based example. The vulnerable pattern is nevertheless supplied as integration code in the Skill instructions and could be copied or activated by an adopter. ### Attack Path 1. An application integrates the documented `openclaw_tts` function. 2. The application permits an untrusted party to influence `output_file`. 3. The attacker supplies a filename containing shell control characters and an additional command. 4. TTS generation returns successfully. 5. The function invokes `start` with `shell=True`. 6. The command shell parses the attacker-controlled filename and executes the injected command with the application user's privileges. ### Impact Assessment Su ...[truncated 447 chars]
Remediation
## Remediation Suggestions - Remove `shell=True` entirely. - On Windows, use `os.startfile()` with a canonicalized local path. - On other platforms, invoke a fixed, trusted playback executable using an argument list and `shell=False`. - Do not allow callers to provide arbitrary output paths unless required. - Generate output filenames internally with `tempfile` and a fixed extension. - Resolve the path and verify that it remains inside the expected temporary directory. - Reject shell metacharacters, device paths, URLs, and unexpected extensions as defense in depth. - Verify that the output is a regular file before opening it. A safer Windows pattern is: ```python from pathlib import Path import os audio_path = Path(output_file).resolve(strict=True) os.startfile(str(audio_path)) ```

T09 · Insecure Skill Coding Practices

Warning
Location
voice_chat.py:88
Finding
Microphone Audio Is Sent to a Cloud Recognition Service Without an Explicit Consent Gate## Vulnerability Details **File Location**: `voice_chat.py:88-100`; equivalent behavior appears in `voice_chat_enhanced.py:198-212`, and automatic connectivity probing appears at `voice_chat_enhanced.py:77-86` **Vulnerability Type**: Unexpected external disclosure of voice data **Risk Level**: Medium ### Vulnerable Code ```python text = self.recognizer.recognize_google( audio, language=self.language, show_all=False ) ``` The enhanced implementation also performs an automatic third-party connectivity request: ```python socket.setdefaulttimeout(3) urllib.request.urlopen('https://www.baidu.com', timeout=3) ``` ### Technical Analysis `recognize_google` submits recorded microphone audio to an external Google speech-recognition service. The primary implementation uses this cloud operation directly, while the enhanced implementation selects Google recognition automatically when dependencies are available. The Skill does mention Google recognition and its network requirement, but it does not implement an explicit, informed consent prompt immediately before the first audio transmission. This is especially significant because `SKILL.md:210-214` recommends local voice-data processing as a privacy measure, and the project also advertises mixed offline and online support. The enhanced script additionally contacts Baidu solely to determine whether network access is available. This request does not contain captured audio, but it discloses network metadata such as the user's IP address and request timing to an unrelated third-party endpoint. It also globally changes the default socket timeout through `socket.setdefaulttimeout(3)`, which can affect unrelated network operations in the same process. ### Attack Path 1. A user launches `voice_chat.py` or selects automatic mode in `voice_chat_enhanced.py`. 2. The application initializes the microphone and records a spoken phrase. 3. The user may assume that voice p ...[truncated 1056 chars]
Remediation
## Remediation Suggestions - Default to a genuinely offline recognition engine. - Before the first cloud request, display a clear consent prompt identifying: - The service receiving the audio. - The type of data transmitted. - Why transmission is required. - Whether retention or account policies may apply. - Store the user's choice only through an explicit configuration mechanism. - Provide a prominent offline-only mode that never attempts external connectivity. - Display a persistent indicator while cloud recognition is active. - Avoid recording until the user has selected or approved the recognition provider. - Remove the Baidu connectivity probe. If a health check is necessary, check the configured recognition endpoint rather than an unrelated website. - Do not call `socket.setdefaulttimeout`; apply timeouts only to individual requests. - Update the privacy documentation to distinguish local simulation, local recognition, and cloud recognition accurately. - Document all external endpoints and provide controls to disable them.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • 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
Findings (30)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
This mismatch becomes security-relevant because the documentation under-describes real behaviors such as network use, local microphone/device access, and shell execution. Users expecting a simple voice-chat sample may unknowingly run code paths that transmit data externally or interact with local system resources.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
This mismatch becomes security-relevant because the documentation under-describes real behaviors such as network use, local microphone/device access, and shell execution. Users expecting a simple voice-chat sample may unknowingly run code paths that transmit data externally or interact with local system resources.

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding
This mismatch becomes security-relevant because the documentation under-describes real behaviors such as network use, local microphone/device access, and shell execution. Users expecting a simple voice-chat sample may unknowingly run code paths that transmit data externally or interact with local system resources.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
if result.returncode == 0:
            print(f"✅ 语音文件已生成: {output_file}")
            # 播放音频
            subprocess.run(["start", output_file], shell=True)
        else:
            print(f"❌ TTS失败: {result.stderr}")
    finally:
Confidence
98% confidence
Finding
The code invokes subprocess.run with shell=True while passing an output_file value that could become attacker-controlled in a modified or integrated version of the sample. On Windows, shell invocation increases command-injection risk and can execute arbitrary commands if the filename or arguments are manipulated.

Env Variable Harvesting

High
Category
Data Exfiltration
Content
def main():
    """自动启动语音对话系统"""
    # 设置环境变量
    env = os.environ.copy()
    env['PYTHONIOENCODING'] = 'utf-8'
    
    print("🚀 正在启动语音对话系统...")
Confidence
60% confidence
Finding
Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The README promotes Google Speech Recognition, Azure/Google Cloud speech, and AI API integration without clearly warning that user voice and transcribed text may be sent to third-party services. In a voice-chat skill, this can expose sensitive spoken content, credentials, or personal data to external providers without informed user consent, making the omission a real privacy/security issue.

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill documents code that uses environment variables, writes files, invokes subprocesses, and sends data over the network, but the manifest declares no corresponding tool scope or permissions. This creates a governance and user-consent gap: consumers may trust the declared metadata while the examples actually require broader capabilities, including microphone access and cloud transmission.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The documentation promotes cloud speech/TTS integrations without clearly warning that user audio or text may be sent to third-party services. In a voice-chat context, this is especially sensitive because spoken input commonly contains personal, confidential, or biometric information.

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
The example code hard-codes `language='zh-CN'` for Google speech recognition, and the Whisper example similarly fixes `language="zh"`. This imposes a specific language/locale without opt-in or configuration, which matches the policy's language/locale violation criteria.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The Whisper example explicitly sets `language="zh"`, requiring Chinese transcription behavior regardless of user preference. The markdown does not offer a language selection mechanism or state that the skill is intentionally restricted to a Chinese-only environment.

External Transmission

Medium
Category
Data Exfiltration
Content
"""使用ElevenLabs TTS"""
    import requests
    
    url = f"https://api.elevenlabs.io/v1/text-to-speech/{voice_id}"
    headers = {
        "xi-api-key": api_key or os.environ.get("ELEVENLABS_API_KEY"),
        "Content-Type": "application/json"
Confidence
88% confidence
Finding
The documented integration targets an external ElevenLabs endpoint, implying third-party transmission of conversation text and use of an API key. The risk is contextual rather than malicious, but it is still a true data-exposure concern when included in a voice-chat skill without clear permission and privacy framing.

External Transmission

Medium
Category
Data Exfiltration
Content
}
    }
    
    response = requests.post(url, json=data, headers=headers)
    if response.status_code == 200:
        with open("output.mp3", "wb") as f:
            f.write(response.content)
Confidence
90% confidence
Finding
This code sends text content to the ElevenLabs API, which is an external transmission of potentially sensitive user data. In a voice assistant context, response text can contain private conversational content, so transmitting it without strong disclosure and consent creates a real privacy risk.

Intent-Code Divergence

Medium
Confidence
97% confidence
Finding
The security notes claim voice data is processed locally, but earlier examples send content to Google speech recognition and ElevenLabs cloud APIs. This is dangerous because users may disclose sensitive voice or text data under a false privacy assumption, causing unintended third-party data exposure.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
# 启动语音对话系统并自动选择选项1
    try:
        # 使用子进程,模拟用户输入
        process = subprocess.Popen(
            [sys.executable, 'voice_chat.py'],
            stdin=subprocess.PIPE,
            stdout=subprocess.PIPE,
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Natural-Language Policy Violations

Medium
Confidence
91% confidence
Finding
The user-facing strings instruct the user to say specific Chinese phrases ('你好' and '退出') to operate the system. This imposes a language requirement in natural-language behavior without any opt-in, fallback, or explanation that the skill is intentionally region- or language-specific.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
This code file contains natural-language strings and comments that consistently force a single language/locale for all user interaction. Under the policy, locale-specific behavior should either offer user opt-in/choice or be clearly justified as region-specific, which is not present here.

Description-Behavior Mismatch

Medium
Confidence
91% confidence
Finding
The file presents itself as an offline voice-dialog test and concludes that all functions work normally, yet the actual behavior is limited to printing preset user/AI text with delays. It does not capture audio, transcribe speech, or synthesize/play speech, so the documented outcome overstates what the code validates.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
模块文档写明这是“不需要网络依赖,演示基本功能”的简化语音对话测试,而技能清单描述该技能应支持基于TTS和STT的完整双向语音交流。代码中的TTS、麦克风和对话流程均只是打印文本或预置字符串模拟,未执行真实语音输入输出,因此实际行为与技能描述存在明显偏差。

Natural-Language Policy Violations

Medium
Confidence
91% confidence
Finding
The file's user-facing descriptions, menu text, prompts, and dialogue content are entirely in Chinese, and the skill does not indicate that language selection is optional or configurable. Under the policy, a skill that implicitly requires a specific language without user opt-in can be a locale-policy violation.

Intent-Code Divergence

Medium
Confidence
93% confidence
Finding
L033 的注释写着“模拟TTS调用”,但紧接着 L035 输出“✅ TTS功能可用(通过OpenClaw tts工具)”,这会让读者误以为代码已实际验证TTS工具。事实上该函数只在终端打印测试文本,没有调用任何语音合成接口,因此文案与实际行为相矛盾。

Natural-Language Policy Violations

Medium
Confidence
87% confidence
Finding
The constructor hard-codes a default language of zh-CN, and the surrounding user-facing text is entirely in Chinese. Under the policy, forcing a specific language or locale without user opt-in is a natural-language policy concern unless the restriction is explicitly justified or users are offered a choice.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The skill captures microphone audio and sends it to Google's remote speech recognition service without a clear, explicit consent flow or prominent privacy disclosure. In a voice-chat context this is more dangerous because users may speak sensitive personal or environmental information, and the transmission happens during normal operation rather than as an exceptional action.

Description-Behavior Mismatch

Medium
Confidence
98% confidence
Finding
The manifest and module documentation describe a complete bidirectional voice chat system using TTS and STT, but the TTS path does not synthesize or play audio. Instead, the code writes a JSON request, prints simulated success messages, and returns True without invoking OpenClaw or producing audible output, so the advertised voice-output behavior is not actually delivered.

Intent-Code Divergence

Medium
Confidence
87% confidence
Finding
The module docstring and method docstring present the system as using OpenClaw TTS for full voice conversation, but the inline comments explicitly say subprocess use is only a simulation and that actual playback is not performed. This is an active contradiction between the code documentation's claimed intent and what the implementation does.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
if sys.platform == "win32":
                os.startfile(audio_file)
            elif sys.platform == "darwin":  # macOS
                subprocess.run(["afplay", audio_file])
            else:  # Linux
                subprocess.run(["aplay", audio_file])
            print("🔊 正在播放音频...")
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Static analysis

No suspicious patterns detected.