Back to skill

Security audit

MLX Audio Server

Security checks for vulnerabilities and agentic risk

Overview

The skill is coherent for a local Mac STT/TTS server, but it automatically installs mutable third-party Homebrew code and starts a persistent background API service with limited scoping and security guidance.

Review before installing. This skill may leave a Mac background audio API running after setup, and it installs the server from a third-party Homebrew tap that can change after review. Prefer localhost-only use, avoid sending sensitive audio or text unless you trust the local server, inspect the Homebrew formula first, and know how to stop or uninstall the service before enabling it.

Vulnerability Patterns
  • System PersistenceInstalls backdoors, hooks, services, or scheduled tasks that survive the run
  • 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 (3)

T08 · Insecure Dependencies

Error
Location
install.sh:5
Finding

Unpinned Third-Party Homebrew Formula Creates a Mutable Supply-Chain Execution Path

Content
View full analysis

Vulnerability Details

File Location: install.sh, lines 5-13
Vulnerability Type: Unverified and unpinned third-party dependency installation
Risk Level: High

Vulnerable Code

bash
brew update

# use brew to install deps if not exists
command -v ffmpeg || brew install ffmpeg
command -v jq || brew install jq

# install formula from tap:
# https://github.com/guoqiao/homebrew-tap/blob/main/Formula/mlx-audio-server.rb
brew install guoqiao/tap/mlx-audio-server || true

Technical Analysis

The installer updates Homebrew metadata and installs mlx-audio-server from the mutable third-party tap guoqiao/tap. The project does not pin the formula to a reviewed commit or version and does not independently verify the formula, downloaded resources, or expected checksums.

A Homebrew formula may execute installation logic and install executable resources. Consequently, the effective code installed by this script can change after the audited Skill package has been published. Compromise of the tap repository, its maintainer account, or an upstream resource referenced by the formula could turn the documented installation command into an arbitrary-code execution channel.

The || true suffix also suppresses installation failure. This can conceal dependency problems and allow execution to continue with an unexpected, stale, or partially installed package.

Attack Path

  1. An attacker compromises or gains update access to the third-party Homebrew tap or one of the formula's mutable upstream resources.
  2. The attacker modifies the formula or referenced package to include malicious installation or runtime behavior.
  3. A user follows the documented instructions and executes install.sh.
  4. brew update obtains current package metadata, and brew install guoqiao/tap/mlx-audio-server retrieves the attacker's modified package.
  5. Homebrew executes the malicious installation logic under the privileges of ...[truncated 737 chars]
Remediation
View remediation

Remediation Suggestions

  • Pin mlx-audio-server and all significant resources to reviewed, immutable versions or commits.
  • Verify downloaded artifacts using cryptographic hashes maintained in a trusted part of this project.
  • Audit and vendor the Homebrew formula where practical instead of relying on a mutable personal tap.
  • Avoid unconditional brew update during installation; document a tested Homebrew state or update dependencies through an explicit user-controlled step.
  • Remove || true from security-relevant installation commands so failures are visible and abort installation.
  • Display the formula source, version, and expected checksums before installation.
  • Consider distributing a signed release and verifying its signature before installing or starting the service.

T06 · System Persistence

Warning
Location
install.sh:11
Finding

Installer Registers a Cross-Session Homebrew Service Without Separate Consent

Content
View full analysis

Vulnerability Details

File Location: install.sh, lines 11-16
Vulnerability Type: Persistent user-level service installation
Risk Level: Medium

Vulnerable Code

bash
# install formula from tap:
# https://github.com/guoqiao/homebrew-tap/blob/main/Formula/mlx-audio-server.rb
brew install guoqiao/tap/mlx-audio-server || true

# (re)start brew service
brew services restart mlx-audio-server || true

Technical Analysis

The installation script automatically invokes brew services restart, which registers or restarts the installed server as a macOS background service. Homebrew services on macOS normally use LaunchAgents or LaunchDaemons and can survive termination of the installer shell and continue across login sessions.

Persistence is consistent with the project's documented goal of providing a 24x7 local server, so this is not concealed behavior. Nevertheless, installation and persistent activation are combined into one operation without a separate confirmation, inspection step, or foreground-only default. The service also executes code obtained from the mutable third-party dependency described in the preceding finding.

The use of || true suppresses service registration errors and can cause the script to proceed to verification without clearly reporting the actual service state.

Attack Path

  1. A user runs the documented install.sh command.
  2. The script installs or reuses the mlx-audio-server formula.
  3. brew services restart mlx-audio-server creates or activates the associated persistent service definition.
  4. The installed server runs in the background after the installation command ends and may restart in later user sessions.
  5. If the formula or installed executable is compromised, its code receives a recurring user-level execution mechanism.

Impact Assessment

The service runs with the privileges assigned by Homebrew, normally those of the installing user when co ...[truncated 412 chars]

Remediation
View remediation

Remediation Suggestions

  • Separate package installation from persistent service activation.
  • Require explicit user confirmation or a documented --enable-service option before registering a background service.
  • Default to running the server in the foreground for initial use and verification.
  • Show the complete LaunchAgent definition, executable path, arguments, environment, and listening address before activation.
  • Remove || true and report service startup failures clearly.
  • Document how to inspect and remove persistence, including:
    bash
    brew services stop mlx-audio-server
    brew uninstall mlx-audio-server
    
  • Ensure the service binds only to loopback by default and runs with the minimum required user permissions.

T09 · Insecure Skill Coding Practices

Warning
Location
run_tts.sh:21
Finding

Unescaped TTS Arguments Permit JSON Request Injection

Content
View full analysis

Vulnerability Details

File Location: run_tts.sh, lines 21-37
Vulnerability Type: Improper construction of JSON from user-controlled input
Risk Level: Medium

Vulnerable Code

bash
data=$(cat <<EOF
{
"instruct": "${instruct}",
"voice": "${voice}",
"gender": "${gender}",
"response_format": "${fmt}",
"model": "${model}",
"input": "${text}"
}
EOF
)

# echo "${data}"

curl -sS -X POST http://localhost:${port}/v1/audio/speech \
  -H "Content-Type: application/json" \
  -d "${data}" --output "${output}"

Technical Analysis

The script interpolates the caller-controlled text value and optional fmt argument directly into a JSON heredoc. Shell quoting does not perform JSON escaping. Inputs containing double quotes, backslashes, newlines, or control characters can therefore produce malformed JSON or inject additional properties.

For example, text shaped like the following can terminate the intended input string and add another JSON member:

text
x", "model": "attacker-selected-model", "input": "x

Whether duplicate properties override earlier values depends on the JSON parser and server implementation. Even when overriding is not possible, malformed input can reliably make the request fail. If the server accepts injected properties, an attacker may alter model selection or other API behavior supported by the endpoint.

The third argument, fmt, is also used in both the JSON request and the output filename without an allowlist. Although the filename is quoted against shell expansion, unexpected format strings can still corrupt the JSON or produce unintended path components and request semantics.

Exploitation requires an attacker to influence arguments supplied to run_tts.sh; the script sends the resulting request only to the configured localhost port.

Attack Path

  1. An attacker supplies or influences text passed as the first argument to run_tts.sh, ...[truncated 1338 chars]
Remediation
View remediation

Remediation Suggestions

  • Construct the request with a JSON-aware encoder rather than string interpolation. For example:
    bash
    data=$(jq -n \
      --arg instruct "$instruct" \
      --arg voice "$voice" \
      --arg gender "$gender" \
      --arg response_format "$fmt" \
      --arg model "$model" \
      --arg input "$text" \
      '{
        instruct: $instruct,
        voice: $voice,
        gender: $gender,
        response_format: $response_format,
        model: $model,
        input: $input
      }')
    
  • Allow only explicitly supported formats, such as wav, using a case statement.
  • Keep the output extension separate from user-controlled directory or path components.
  • Reject input containing unsupported control characters if the downstream API imposes additional restrictions.
  • Use curl --fail-with-body and verify the response content type and status before treating the output as valid audio.
  • Add tests covering quotes, backslashes, multiline text, Unicode, and JSON-like input.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (8)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The README explicitly promotes running the package as a 24x7 LaunchAgent-backed API server but does not warn users that this creates a continuously running background service with an HTTP endpoint. In a security-sensitive context, omission of persistence and exposure details can cause users to unintentionally leave speech-processing services reachable longer than expected, increasing the chance of unauthorized local or network access depending on bind behavior.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The README instructs users to connect via http://<IP>:8899, which encourages use over a non-local network without warning that audio and transcripts may traverse the network unencrypted and that the service may be reachable by other hosts. For an OpenAI-compatible speech API, this can expose sensitive voice data, transcripts, and service access if the server is not authenticated and not limited to localhost.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill exposes shell-based installation and execution behavior but does not declare any tool scope or permissions boundary. That creates ambiguity for agents and users about what system-level actions the skill may perform, increasing the chance of unreviewed command execution and unsafe automation.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The manifest sets the skill to run "always," which broadens activation without a narrowly defined trigger or user-scoped condition. In a skill that installs software and manages a persistent local service, overbroad activation increases the risk of unexpected execution and repeated system changes.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The installation section says it will start a brew service for mlx-audio-server, but the skill description does not prominently warn that this creates a persistent background LaunchAgent on the user's macOS system. Persistent services change the host's security posture, may expose a local API continuously, and can survive beyond the immediate task, so insufficient disclosure is materially risky.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The script posts the provided audio file to a server endpoint using curl, which transmits potentially sensitive user data. Although the behavior is visible in code, there is no confirmation prompt, user-facing log message, or other disclosure in this file warning that audio contents will be sent to a service.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · run_tts.sh (reported line 35)May include surrounding context.

sh
# echo "${data}"

curl -sS -X POST http://localhost:${port}/v1/audio/speech \
  -H "Content-Type: application/json" \
  -d "${data}" --output "${output}"

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The script posts the full input text in JSON to an HTTP service on localhost and writes the returned audio to disk, but there is no confirmation prompt, warning message, or explanatory comment disclosing that user input is transmitted to another service. Because transmitted text may contain sensitive content, this is a safety-relevant operation that should be made explicit to users.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.