Back to skill

Security audit

iMessage Voice Reply

Security checks for vulnerabilities and agentic risk

Overview

This skill is purpose-aligned for generating local TTS audio and sending it through BlueBubbles, but users should review its dependency install and temporary-file handling.

Install only if you are comfortable letting the skill install Python packages from the package index, cache Kokoro model files locally, create temporary audio/text files, and send iMessage attachments through BlueBubbles. Prefer reviewing or pinning dependencies and using private mktemp-created directories instead of the documented fixed /tmp filenames.

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

Error
Location
scripts/setup.sh:16
Finding
Unpinned Third-Party Dependencies Allow Supply-Chain Compromise## Vulnerability Details **File Location**: `scripts/setup.sh`, lines 16-18 **Vulnerability Type**: Unverified and unpinned runtime dependency installation **Risk Level**: High **Vulnerable Code**: ```bash echo "📦 Installing Python dependencies..." "$VENV_DIR/bin/pip" install -q --upgrade pip "$VENV_DIR/bin/pip" install -q kokoro-onnx soundfile numpy ``` ### Technical Analysis The setup process installs the latest available versions of `kokoro-onnx`, `soundfile`, and `numpy` without a lock file, exact version constraints, or package hashes. It also upgrades `pip` to an unspecified version. Consequently, the code installed and executed by this skill can change independently of the reviewed project. Python packages can execute code during installation and whenever their modules are imported. The generated virtual environment is subsequently used to import these dependencies. If a package release, package-index account, distribution artifact, or dependency is compromised, attacker-controlled code could run under the account invoking the setup or generation script. ### Attack Path 1. An attacker compromises a named package, one of its transitive dependencies, its publishing account, or the configured Python package index. 2. The attacker publishes a malicious release that still satisfies the unconstrained installation command. 3. A user runs `scripts/setup.sh`. 4. `pip` resolves and installs the malicious release without checking an expected version or artifact hash. 5. Malicious code executes during installation or when `generate_voice_reply.py` imports the installed package. 6. The code operates with the filesystem, process, and network privileges of the user running the skill. ### Impact Assessment Successful exploitation can result in arbitrary code execution with the invoking user's privileges. This may expose files, environment variables, local credentials, message content, and BlueBubbles-related data accessi ...[truncated 229 chars]
Remediation
## Remediation Suggestions - Pin every direct dependency to a reviewed exact version. - Generate a lock file that also fixes all transitive dependency versions. - Record cryptographic hashes for every approved distribution and install with `pip --require-hashes`. - Use a controlled package index or an internally mirrored repository containing reviewed artifacts. - Avoid automatically upgrading `pip`; instead, pin it to a separately reviewed version. - Prefer binary wheels from trusted sources where appropriate and verify package provenance or signatures when available. - Add automated dependency vulnerability and integrity checks to the release process.

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:32
Finding
Predictable Shared Temporary Paths in the Documented Workflow## Vulnerability Details **File Location**: `SKILL.md`, lines 32-37 **Vulnerability Type**: Predictable temporary files and potential symbolic-link attacks **Risk Level**: Medium **Vulnerable Code**: ```bash Write the response text to a temp file, then pass it via `--text-file` to avoid shell injection: ```bash echo "Your response text here" > /tmp/voice_text.txt ${baseDir}/.venv/bin/python ${baseDir}/scripts/generate_voice_reply.py --text-file /tmp/voice_text.txt --output /tmp/voice_reply.caf ``` ``` ### Technical Analysis The documented operational workflow uses fixed names in the system-wide `/tmp` directory. Such paths can collide across users, sessions, or concurrent requests. On systems where another local process can create entries in `/tmp`, an attacker may pre-create either path as a symbolic link to another file. Shell redirection to `/tmp/voice_text.txt` follows symbolic links under ordinary filesystem behavior. The encoder also receives `/tmp/voice_reply.caf` as a caller-selected output path. In addition, the plaintext response remains at a predictable location because the example does not remove it after processing. Although this weakness appears in documentation rather than an automatically invoked wrapper, agents are explicitly instructed to execute these commands. It therefore represents an exploitable recommended usage pattern. ### Attack Path 1. A local attacker anticipates that the documented voice-reply workflow will be used. 2. The attacker creates `/tmp/voice_text.txt` or `/tmp/voice_reply.caf` as a symbolic link to a file writable by the victim account, or creates a colliding file used to influence the operation. 3. The agent executes the documented commands. 4. Shell redirection or the audio encoder follows the attacker-controlled path. 5. Data may be written to an unintended target, the generated audio may be replaced or corrupted, or response text may become available through the predict ...[truncated 573 chars]
Remediation
## Remediation Suggestions - Replace fixed `/tmp` paths with a private directory created by `mktemp -d`. - Set a restrictive umask, such as `umask 077`, before creating files. - Store uniquely named input and output files inside that private directory. - Register a shell `trap` to remove the directory and its contents on normal exit, interruption, or failure. - Avoid writing untrusted text with interpolated `echo`; provide it through a safely created file or another interface that does not involve shell expansion. - Ensure output creation rejects existing files or symbolic links where supported. - Document safe concurrent operation rather than presenting globally shared filenames as the recommended workflow.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/generate_voice_reply.py:27
Finding
Race-Prone Temporary File Creation with tempfile.mktemp## Vulnerability Details **File Location**: `scripts/generate_voice_reply.py`, lines 27-40 and 100-101 **Vulnerability Type**: Time-of-check to time-of-use race involving temporary files **Risk Level**: Medium **Vulnerable Code**: ```python def encode_caf_afconvert(wav_path: str, out_path: str) -> None: """Encode to CAF/Opus using Apple's native afconvert (macOS only).""" wav48 = tempfile.mktemp(suffix="_48k.wav") try: subprocess.run( ["afconvert", wav_path, "-o", wav48, "-d", "LEI16", "-c", "1", "-r", "48000"], capture_output=True, check=True, ) subprocess.run( ["afconvert", wav48, "-o", out_path, "-f", "caff", "-d", "opus", "-b", "32000"], capture_output=True, check=True, ) finally: if os.path.exists(wav48): os.unlink(wav48) ``` ```python # Write intermediate WAV wav_path = tempfile.mktemp(suffix=".wav") sf.write(wav_path, samples, sr) ``` ### Technical Analysis `tempfile.mktemp()` selects and returns an unused-looking pathname but does not atomically create the file. A window therefore exists between pathname selection and its later use by `soundfile` or `afconvert`. Another local process can attempt to create a file or symbolic link at the selected path during this interval. The first intermediate path is opened for writing by `sf.write`. The second is passed to an external encoder as an output destination and then reused as input. The `finally` block performs a separate existence check before unlinking, which does not correct the insecure initial creation and can itself operate on a path whose directory entry changed during execution. The subprocess calls correctly use argument lists without `shell=True`, so this issue is not shell-command injection. The weakness is specifically insecure temporary-file lifecycle management. ### Attack Path 1. A local attacker monitors the ...[truncated 1137 chars]
Remediation
## Remediation Suggestions - Replace every use of `tempfile.mktemp()` with `tempfile.NamedTemporaryFile`, `tempfile.mkstemp`, or `tempfile.TemporaryDirectory`. - Create temporary files atomically with restrictive permissions before passing their paths to libraries or external encoders. - Prefer a private `TemporaryDirectory` with mode `0700`, then create all intermediate files inside it. - If an external tool requires a pathname, securely create the containing private directory and ensure the generated target cannot be replaced by an untrusted user. - Place creation, encoding, and cleanup in a single `try`/`finally` structure so the initial WAV is also removed after conversion failures. - Avoid separate check-then-unlink logic where possible; handle `FileNotFoundError` during direct cleanup instead.
Vulnerability Patterns
  • Rogue AgentSelf-Modification, Session Persistence
  • 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
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (8)

Lp3

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding
The skill instructs the agent to execute shell commands and read/write local files, but it does not declare any explicit tool scope such as permissions or allowed-tools. This creates a least-privilege violation: an agent or runtime may grant broader capabilities than intended, increasing the blast radius if the skill is misused or if later edits introduce unsafe command/data handling.

Intent-Code Divergence

Medium
Confidence
94% confidence
Finding
The top-level docstring states the script generates a native iMessage voice message, which implies CAF/Opus output compatible with inline playback. But the documented behavior in the same docstring and the implementation include an ffmpeg-based MP3 fallback on other platforms, contradicting the claim of always producing a native iMessage voice message.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
"""Encode to CAF/Opus using Apple's native afconvert (macOS only)."""
    wav48 = tempfile.mktemp(suffix="_48k.wav")
    try:
        subprocess.run(
            ["afconvert", wav_path, "-o", wav48, "-d", "LEI16", "-c", "1", "-r", "48000"],
            capture_output=True, check=True,
        )
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
["afconvert", wav_path, "-o", wav48, "-d", "LEI16", "-c", "1", "-r", "48000"],
            capture_output=True, check=True,
        )
        subprocess.run(
            ["afconvert", wav48, "-o", out_path, "-f", "caff", "-d", "opus", "-b", "32000"],
            capture_output=True, check=True,
        )
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Description-Behavior Mismatch

Medium
Confidence
96% confidence
Finding
The manifest describes the skill as generating native iMessage voice bubbles using CAF/Opus rather than file attachments. However, this script explicitly implements a non-macOS fallback that encodes MP3 output, and later selects that path when afconvert is unavailable, which does not match the described native iMessage voice-bubble behavior.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
def encode_mp3_ffmpeg(wav_path: str, out_path: str) -> None:
    """Encode to MP3 using ffmpeg (cross-platform fallback)."""
    subprocess.run(
        ["ffmpeg", "-y", "-i", wav_path, "-ar", "44100", "-ac", "1",
         "-c:a", "libmp3lame", "-b:a", "128k", out_path],
        capture_output=True, check=True,
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Session Persistence

Medium
Category
Rogue Agent
Content
# Download Kokoro models
if [ ! -f "$KOKORO_DIR/kokoro-v1.0.onnx" ] || [ ! -f "$KOKORO_DIR/voices-v1.0.bin" ]; then
    echo "🧠 Downloading Kokoro TTS models (~136MB)..."
    mkdir -p "$KOKORO_DIR"
    "$VENV_DIR/bin/python" -c "
from kokoro_onnx import Kokoro
import os
Confidence
60% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Natural-Language Policy Violations

Low
Confidence
85% confidence
Finding
The CLI sets a default language code of "en-us", which imposes a specific locale whenever the caller does not explicitly choose one. The policy allows locale constraints only when the user is given a choice or the constraint is clearly justified, neither of which is documented here.

Static analysis

No suspicious patterns detected.