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

Content
View full analysis

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

Content
View full analysis

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
text

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

Content
View full analysis

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

Undeclared Tool Scope

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.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

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

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/generate_voice_reply.py (reported line 31)May include surrounding context.

python
"""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 module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/generate_voice_reply.py (reported line 35)May include surrounding context.

python
["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,
        )

Description-Behavior Mismatch

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

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/generate_voice_reply.py (reported line 46)May include surrounding context.

python
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,

Session Persistence

Medium
Category
Rogue Agent
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.

Content

Scanner excerpt · scripts/setup.sh (reported line 24)May include surrounding context.

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

Natural-Language Policy Violations

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

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.