Back to skill

Security audit

Openclaw Mlx Audio

Security checks for vulnerabilities and agentic risk

Overview

The skill appears to be a real local audio plugin, but its installer runs mutable remote code and force-installs unpinned prerelease dependencies.

Review the installer before running it. Prefer installing uv and mlx-audio through pinned, trusted package-manager commands, avoid the README cache-deletion command unless you understand exactly what it removes, and only use transcription or voice-cloning features with audio you are authorized to process.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • 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
Findings (4)

T03 · Remote Payload Retrieval and Execution

Error
Location
install.sh:34
Finding
Remote Installer Is Downloaded and Executed Without Integrity Verification## Vulnerability Details **File Location**: `install.sh:34-38`; duplicated in installation guidance at `README.md:76-82` **Vulnerability Type**: Remote payload retrieval and execution **Risk Level**: High ### Vulnerable Code ```bash # Install uv if missing if ! check_command uv; then echo "📦 Installing uv..." curl -LsSf https://astral.sh/uv/install.sh | sh export PATH="$HOME/.local/bin:$PATH" fi ``` The README instructs users to perform the same operation: ```bash # 2. Install uv curl -LsSf https://astral.sh/uv/install.sh | sh # 3. Install mlx-audio uv tool install --force mlx-audio --prerelease=allow ``` ### Technical Analysis The installer pipes an HTTPS response directly into a shell. Although `astral.sh` is associated with the legitimate `uv` project, the downloaded content is mutable and is neither version-pinned nor authenticated with a published checksum or signature. This means the effective code executed during installation can differ from the code reviewed in this project. A compromise of the upstream website, delivery infrastructure, DNS/TLS trust chain, or installer publishing process could result in arbitrary shell commands being returned and immediately executed. Installing `uv` is relevant to the Skill's functionality, but directly executing an unverified remote response exceeds the minimum privilege and trust necessary to install that dependency safely. ### Attack Path 1. An attacker compromises the upstream installer endpoint or an element of its delivery chain. 2. The attacker modifies the response from `https://astral.sh/uv/install.sh`. 3. A user runs `./install.sh` or copies the command from the README. 4. `curl` downloads the attacker-controlled response. 5. The pipe passes the response directly to `sh` without inspection or integrity verification. 6. The payload executes with all permissions of the user running the installer. ### Impact Assessment A s ...[truncated 607 chars]
Remediation
## Remediation Suggestions 1. Remove all `curl | sh` instructions from both `install.sh` and `README.md`. 2. Prefer installation through a trusted operating-system package manager, such as: ```bash brew install uv ``` 3. If direct installation is necessary: - Pin a specific `uv` release. - Download the release artifact to disk. - Verify a publisher-provided cryptographic checksum or signature. - Abort installation if verification fails. - Execute the verified local artifact only after validation. 4. Display the exact version and source that will be installed before changing the system. 5. Avoid requesting elevated privileges for any dependency that can be installed within the user's account.

T08 · Insecure Dependencies

Warning
Location
install.sh:41
Finding
Unpinned Prerelease Dependency Is Force-Installed## Vulnerability Details **File Location**: `install.sh:41-43`; equivalent instructions appear at `README.md:79-82` and `SKILL.md:38-39` **Vulnerability Type**: Insecure dependency installation **Risk Level**: Medium ### Vulnerable Code ```bash # Install mlx-audio via uv tool echo "📦 Installing mlx-audio..." uv tool install --force mlx-audio --prerelease=allow ``` The Skill instructions contain the same unpinned installation pattern: ```bash brew install ffmpeg uv uv tool install mlx-audio --prerelease=allow ``` ### Technical Analysis The command does not specify an exact `mlx-audio` version and explicitly permits prerelease versions. Consequently, separate installations of the same reviewed Skill may resolve to different dependency code. The `--force` option replaces an existing installation even when a compatible or previously audited version is already present. This increases exposure to newly published, compromised, or incompatible releases. Because the installed CLI is later executed by the plugin, dependency code receives local code-execution capability under the OpenClaw account. No evidence was found that the current `mlx-audio` package is malicious. The vulnerability is the absence of dependency immutability and integrity controls. ### Attack Path 1. A malicious or compromised release becomes available from the package source under the `mlx-audio` package name. 2. The release qualifies for installation because no exact version is specified and prereleases are allowed. 3. A user runs `install.sh`. 4. `uv tool install --force` resolves and installs the new release, replacing any existing version. 5. Package installation logic or subsequent calls to `mlx_audio.tts.generate` and `mlx_audio.stt.generate` execute the compromised dependency. ### Impact Assessment Exploitation could provide arbitrary code execution with the permissions of the user running installation or OpenClaw. This includes a ...[truncated 288 chars]
Remediation
## Remediation Suggestions 1. Pin `mlx-audio` to an exact audited version: ```bash uv tool install "mlx-audio==<audited-version>" ``` 2. Do not enable prereleases in production installation instructions. 3. Use a lock file or requirements file containing hashes for all transitive dependencies. 4. Remove `--force` from the default installation path. Make replacement of an existing installation an explicit user decision. 5. Verify package provenance and publish the expected package index, exact version, checksums, and update policy. 6. Test upgrades separately before changing the pinned release.

T09 · Insecure Skill Coding Practices

Warning
Location
python-runtime/stt_server.py:106
Finding
STT Server Uses Race-Prone Temporary Output Path## Vulnerability Details **File Location**: `python-runtime/stt_server.py:106-125` **Vulnerability Type**: Unsafe temporary-file handling **Risk Level**: Medium ### Vulnerable Code ```python # Save to temp file with tempfile.NamedTemporaryFile(delete=False, suffix=".wav") as tmp: tmp.write(audio_data) tmp_path = tmp.name output_base = tempfile.mktemp() # Call CLI cmd = [ "mlx_audio.stt.generate", "--model", model, "--audio", tmp_path, "--format", "txt", "--output", output_base ] if language: cmd.extend(["--language", language]) logger.info(f"Running: {' '.join(cmd)}") subprocess.run(cmd, check=True, capture_output=True) # Read result txt_path = Path(f"{output_base}.txt") ``` ### Technical Analysis `tempfile.mktemp()` returns an unused pathname but does not atomically create and reserve the corresponding file. Python explicitly discourages this API because another local process can create a file or symbolic link at the returned path before the application or downstream CLI uses it. The generated path is passed to `mlx_audio.stt.generate`, which is expected to create `${output_base}.txt`. This creates a time-of-check/time-of-use window. If the downstream CLI follows symbolic links, a local attacker able to win the race could redirect output to another file writable by the server account. An attacker could also pre-create the output file to manipulate the transcription result read by the server. The audio input uses `NamedTemporaryFile`, which is safer, but the output does not receive the same protection. ### Attack Path 1. The STT server calls `tempfile.mktemp()` and receives a currently unused path. 2. Before `mlx_audio.stt.generate` creates the output, a local attacker identifies or races the temporary pathname. 3. The attacker creates `${output_base}.txt` as a symbolic link or attacker-controlled file. 4. The STT CLI writes to that path, or the serv ...[truncated 728 chars]
Remediation
## Remediation Suggestions 1. Replace `tempfile.mktemp()` with a private temporary directory: ```python with tempfile.TemporaryDirectory() as temp_dir: output_base = str(Path(temp_dir) / "transcription") ``` 2. Ensure the temporary directory is accessible only to the service account. 3. Keep input and output artifacts inside the same private per-request directory. 4. Verify that the expected output is a regular file and not a symbolic link before reading it. 5. Perform cleanup in a `finally` block so files are removed after failures as well as successful requests. 6. Run the inference process under a dedicated, minimally privileged account if the HTTP server is deployed.

T09 · Insecure Skill Coding Practices

Warning
Location
python-runtime/tts_server.py:61
Finding
TTS Server Uses a Predictable Shared Output Path Without Secure Cleanup## Vulnerability Details **File Location**: `python-runtime/tts_server.py:61-79` **Vulnerability Type**: Predictable temporary path and unsafe file lifecycle **Risk Level**: Medium ### Vulnerable Code ```python # Generate output path output_dir = Path("/tmp/mlx-tts") output_dir.mkdir(parents=True, exist_ok=True) output_path = output_dir / f"speech_{os.getpid()}.{output_format}" # Call CLI cmd = [ "mlx_audio.tts.generate", "--model", req.get("model", MODEL), "--text", text, "--voice", voice, "--speed", str(speed), "--lang_code", language, "--output_path", str(output_path), "--audio_format", output_format ] logger.info(f"Running: {' '.join(cmd)}") subprocess.run(cmd, check=True, capture_output=True) if not output_path.exists(): # Try wav fallback output_path = output_path.with_suffix(".wav") ``` ### Technical Analysis The server stores generated audio under a fixed directory in the system-wide temporary area and derives the filename solely from the server PID and client-controlled format. Every request handled by the same process therefore reuses a predictable output path for a given format. The code does not verify ownership or permissions when `/tmp/mlx-tts` already exists, does not reject symbolic links, and does not atomically reserve the output file. A local attacker could pre-create the directory or predicted output path before server startup. If the downstream CLI follows symbolic links, generated output could be redirected to another file writable by the server account. Generated audio is also not deleted after it is returned. This leaves speech content on disk and can expose stale output to other processes with access to the directory. Reusing the same path may also cause a failed generation to return an older file if that file remains present. ### Attack Path 1. A local attacker predicts the server PID or observes the running process. 2. ...[truncated 890 chars]
Remediation
## Remediation Suggestions 1. Create a private temporary directory for each request: ```python with tempfile.TemporaryDirectory(prefix="mlx-tts-") as temp_dir: output_path = Path(temp_dir) / f"speech.{validated_format}" ``` 2. Restrict output formats to a fixed allowlist such as `mp3` and `wav`. 3. Verify that output files are regular files owned by the service account and reject symbolic links. 4. Remove generated output in a `finally` block immediately after sending the response. 5. Do not reuse a PID-derived filename across requests; use cryptographically random, atomically created paths. 6. Validate ownership and permissions of any persistent runtime directory before using it. 7. Run the server with a dedicated low-privilege account and keep its temporary directory inaccessible to other users.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • 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 (72)

Chaining Abuse

High
Category
Tool Misuse
Content
brew install ffmpeg

# 2. 安装 uv
curl -LsSf https://astral.sh/uv/install.sh | sh

# 3. 安装 mlx-audio
uv tool install --force mlx-audio --prerelease=allow
Confidence
96% confidence
Finding
The `| sh` chain immediately turns downloaded network content into shell execution, removing any opportunity for review and magnifying the impact of upstream compromise. In install documentation, this pattern is particularly dangerous because it normalizes unsafe behavior for end users and can lead to full local compromise.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
Run: ./install.sh

# 清除缓存重试
rm -rf ~/.cache/huggingface/hub/models--mlx-community--*

# 检查配置
openclaw doctor
Confidence
93% confidence
Finding
The documented `rm -rf ~/.cache/huggingface/hub/models--mlx-community--*` command is destructive and uses a wildcard path, which can remove multiple local model caches without confirmation. In troubleshooting-oriented skill docs, users are especially likely to copy-paste such commands, so the context increases the chance of unintended data loss and service disruption.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
Run: ./install.sh

# 清除缓存重试
rm -rf ~/.cache/huggingface/hub/models--mlx-community--*

# 检查配置
openclaw doctor
Confidence
93% confidence
Finding
The documented `rm -rf ~/.cache/huggingface/hub/models--mlx-community--*` command is destructive and uses a wildcard path, which can remove multiple local model caches without confirmation. In troubleshooting-oriented skill docs, users are especially likely to copy-paste such commands, so the context increases the chance of unintended data loss and service disruption.

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding
The documented tool examples allow arbitrary outputPath and audioPath values while the manifest does not disclose filesystem or process-execution behavior. In a skill that handles local files and invokes external CLIs, this mismatch is dangerous because users may trigger reads/writes or command-driven processing against sensitive local paths without understanding the scope.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The documented tool examples allow arbitrary outputPath and audioPath values while the manifest does not disclose filesystem or process-execution behavior. In a skill that handles local files and invokes external CLIs, this mismatch is dangerous because users may trigger reads/writes or command-driven processing against sensitive local paths without understanding the scope.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The documented tool examples allow arbitrary outputPath and audioPath values while the manifest does not disclose filesystem or process-execution behavior. In a skill that handles local files and invokes external CLIs, this mismatch is dangerous because users may trigger reads/writes or command-driven processing against sensitive local paths without understanding the scope.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The documented tool examples allow arbitrary outputPath and audioPath values while the manifest does not disclose filesystem or process-execution behavior. In a skill that handles local files and invokes external CLIs, this mismatch is dangerous because users may trigger reads/writes or command-driven processing against sensitive local paths without understanding the scope.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The documented tool examples allow arbitrary outputPath and audioPath values while the manifest does not disclose filesystem or process-execution behavior. In a skill that handles local files and invokes external CLIs, this mismatch is dangerous because users may trigger reads/writes or command-driven processing against sensitive local paths without understanding the scope.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The documented tool examples allow arbitrary outputPath and audioPath values while the manifest does not disclose filesystem or process-execution behavior. In a skill that handles local files and invokes external CLIs, this mismatch is dangerous because users may trigger reads/writes or command-driven processing against sensitive local paths without understanding the scope.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The documented tool examples allow arbitrary outputPath and audioPath values while the manifest does not disclose filesystem or process-execution behavior. In a skill that handles local files and invokes external CLIs, this mismatch is dangerous because users may trigger reads/writes or command-driven processing against sensitive local paths without understanding the scope.

Chaining Abuse

High
Category
Tool Misuse
Content
if command -v brew &> /dev/null; then
        brew install ffmpeg
    elif command -v apt-get &> /dev/null; then
        sudo apt-get update && sudo apt-get install -y ffmpeg
    elif command -v dnf &> /dev/null; then
        sudo dnf install -y ffmpeg
    else
Confidence
75% confidence
Finding
Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Chaining Abuse

High
Category
Tool Misuse
Content
# Install uv if missing
if ! check_command uv; then
    echo "📦 Installing uv..."
    curl -LsSf https://astral.sh/uv/install.sh | sh
    export PATH="$HOME/.local/bin:$PATH"
fi
Confidence
99% confidence
Finding
The '| sh' construct turns downloaded network content directly into executable shell commands, which is a classic unsafe chaining pattern. Because this is an installer script that users are likely to run locally, successful compromise of the upstream script would provide immediate arbitrary code execution on the host.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
fi

# 清理
rm -f /tmp/test_output_*.txt

# 退出码
if [ $FAILED -gt 0 ]; then
Confidence
95% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Natural-Language Policy Violations

Medium
Confidence
85% confidence
Finding
The document is primarily written in Chinese and gives operational instructions in that language, but it does not offer an alternate language option or state that the skill is intentionally limited to a Chinese-speaking context. This can violate a language/locale policy when users are not given opt-in or choice.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The test plan explicitly covers sending voice messages, transcribing them, extracting voice features, and cloning voices, but it does not mention user consent, retention limits, disclosure, or handling of biometric/voice data. In a Discord-integrated audio skill, this omission can lead to privacy violations, unauthorized voice cloning, and unsafe collection or reuse of sensitive user audio.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The report is written entirely in Chinese, including operational instructions and status information, with no indication that users can choose another language or locale. This can violate a language/locale policy when the skill materials impose a specific language by default without user opt-in or documented regional justification.

Intent-Code Divergence

Medium
Confidence
94% confidence
Finding
The README says the current dependency model is 'CLI only' and the changelog says the Python API was removed. Later sections contradict that by describing `python-runtime/tts_server.py` and `stt_server.py` as lightweight HTTP services and by stating HTTP service support is optional. This is an active contradiction in the documentation about what the codebase contains and how it operates.

Description-Behavior Mismatch

Medium
Confidence
88% confidence
Finding
The manifest describes the skill as a local TTS/STT integration using mlx-audio with zero cloud dependency, which fits a local implementation. However, the README repeatedly claims the architecture is now 'CLI only' and that the Python API was removed, while also documenting optional HTTP services and listing `tts_server.py` and `stt_server.py` as part of the project structure. That broadens the described behavior beyond the claimed simplified CLI-only operation.

Natural-Language Policy Violations

Medium
Confidence
91% confidence
Finding
The sample configuration hard-codes `langCode: "zh"` and `language: "zh"`, and the document overall presents the skill as Chinese-first without offering an opt-in choice for other supported languages. This is a natural-language locale policy concern because the documentation steers users toward a fixed language setting without explaining that it is optional or region-specific.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The README recommends a destructive cache-deletion command without explaining scope, side effects, or safer alternatives. Users may delete local model caches or unrelated data matching the glob, causing data loss, bandwidth waste, and disruption, especially when copying commands blindly from troubleshooting steps.

File System Enumeration

Medium
Category
Data Exfiltration
Content
openclaw doctor

# 检查插件目录
ls -la ~/.openclaw/extensions/openclaw-mlx-audio/dist/

## 开发笔记
Confidence
60% confidence
Finding
Code scans file system directories looking for sensitive files. This could be reconnaissance for credential theft.

Natural-Language Policy Violations

Medium
Confidence
91% confidence
Finding
The sample configuration hard-codes `langCode: "zh"` and `language: "zh"`, which indicates a specific language/locale is being imposed. The document does not present this as optional, configurable by user preference, or justified as a region-specific tool, so it fits the language/locale policy violation category.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The release guidance promotes enabling STT and voice-cloning capabilities and even public publication, but it does not warn about consent, retention, misuse, or other privacy implications of processing biometric voice data. In the context of an audio/voice skill, this omission materially increases the chance that operators deploy sensitive functionality without user notice, policy guardrails, or abuse controls.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The sample configuration hard-codes `langCode: "zh"` for TTS and `language: "zh"` for STT, which imposes a specific language/locale in the documented setup. The file does not offer a user choice or explain that this is an example for a region-specific deployment, so it reads as a language policy constraint.

Lp3

Medium
Category
MCP Least Privilege
Confidence
86% confidence
Finding
The skill advertises operational behavior that inherently requires shell execution and filesystem access, but it does not declare any tool scope such as permissions or allowed-tools. That creates a transparency and policy-enforcement gap: the host may permit actions the user did not explicitly approve, including reading local audio files and writing synthesized output to arbitrary paths.

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
dist/index.js:45

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
src/index.ts:71