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

Content
View full analysis

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
View 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

Content
View full analysis

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
View 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

Content
View full analysis

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
View 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

Content
View full analysis

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.

...[truncated 890 chars]

Remediation
View 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
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.

Content

Scanner excerpt · README.md (reported line 79)May include surrounding context.

md
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

Tool Parameter Abuse

High
Category
Tool Misuse
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.

Content

Scanner excerpt · README.md (reported line 172)May include surrounding context.

md
Run: ./install.sh

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

# 检查配置
openclaw doctor

Tool Parameter Abuse

High
Category
Tool Misuse
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.

Content

Scanner excerpt · README.md (reported line 172)May include surrounding context.

md
Run: ./install.sh

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

# 检查配置
openclaw doctor

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.

Content

No source excerpt is available for this finding.

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.

Content

No source excerpt is available for this finding.

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.

Content

No source excerpt is available for this finding.

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.

Content

No source excerpt is available for this finding.

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.

Content

No source excerpt is available for this finding.

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.

Content

No source excerpt is available for this finding.

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.

Content

No source excerpt is available for this finding.

Chaining Abuse

High
Category
Tool Misuse
Confidence
75% confidence
Finding

Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Content

Scanner excerpt · install.sh (reported line 25)May include surrounding context.

sh
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

Chaining Abuse

High
Category
Tool Misuse
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.

Content

Scanner excerpt · install.sh (reported line 37)May include surrounding context.

sh
# 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

Tool Parameter Abuse

High
Category
Tool Misuse
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).

Content

Scanner excerpt · test/run_tests.sh (reported line 92)May include surrounding context.

sh
fi

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

# 退出码
if [ $FAILED -gt 0 ]; then

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

File System Enumeration

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code scans file system directories looking for sensitive files. This could be reconnaissance for credential theft.

Content

Scanner excerpt · README.md (reported line 178)May include surrounding context.

md
openclaw doctor

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

## 开发笔记

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

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.

Content

No source excerpt is available for this finding.