Back to skill

Security audit

NEXUS Voice Transcriber

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent voice transcription tool, but its URL download and split-file cleanup behavior are under-scoped enough to require review before installation.

Install only if you are comfortable with a transcription skill that can write archives under your home directory, optionally upload audio to Deepgram, and fetch remote URLs. Prefer local Whisper for sensitive audio, avoid passing untrusted URLs, do not run --split in directories containing important chunk_* files, and install dependencies in a virtual environment with pinned versions where possible.

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)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/transcribe.py:87
Finding

Wildcard-Based Cleanup Can Delete Unrelated User Files

Content
View full analysis

Vulnerability Details

File Location: scripts/transcribe.py, lines 87–96 and 406–414
Vulnerability Type: Unsafe file discovery and deletion
Risk Level: High

Vulnerable Code:

python
def split_audio_ffmpeg(audio_path: Path, chunk_sec: int = 600) -> list[Path]:
    """Split audio into chunks of chunk_sec seconds. Returns list of chunk paths."""
    chunk_pattern = audio_path.parent / f"chunk_%03d{audio_path.suffix}"
    cmd = [
        "ffmpeg", "-y", "-i", str(audio_path),
        "-f", "segment", "-segment_time", str(chunk_sec),
        "-c", "copy", str(chunk_pattern)
    ]
    try:
        subprocess.run(cmd, check=True, capture_output=True)
        # collect generated chunks
        chunks = sorted(audio_path.parent.glob("chunk_*" + audio_path.suffix))
        print(f"Split into {len(chunks)} chunks")
        return chunks
python
if args.split and len(chunks) > 1:
    # remove chunk files (they are in same dir as original or temp)
    for chunk in chunks:
        try:
            chunk.unlink()
        except:
            pass

Technical Analysis

Audio chunks are created directly in the input file's parent directory using a predictable chunk_NNN naming pattern. After ffmpeg finishes, the script does not record which files were actually created during the current operation. Instead, it uses the broad wildcard chunk_* with the input suffix and assumes every matching file is one of its temporary artifacts.

Cleanup subsequently calls unlink() on every discovered match. Consequently, pre-existing files such as chunk_archive.mp3 or chunks produced by another concurrent process can be included and deleted. The bare except suppresses deletion errors and makes the resulting data loss less visible.

Attack Path

  1. An attacker or another user places two or more files named chunk_*.mp3 in a directory containing an MP3 input file.
  2. The victi ...[truncated 711 chars]
Remediation
View remediation

Remediation Suggestions

  • Create a unique temporary directory for each split operation using tempfile.TemporaryDirectory().
  • Direct ffmpeg output exclusively into that isolated directory.
  • Capture and retain an explicit list of files created by the current operation.
  • Delete only files inside the dedicated temporary directory instead of globbing in the user's input directory.
  • Verify resolved paths remain beneath the expected temporary root before deleting them.
  • Replace the bare except with a specific exception such as OSError and report cleanup failures.
  • Use a try/finally block or a temporary-directory context manager so cleanup occurs safely even if transcription fails.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/transcribe.py:50
Finding

Unrestricted URL Download Enables Server-Side Request Forgery and Disk Exhaustion

Content
View full analysis

Vulnerability Details

File Location: scripts/transcribe.py, lines 50–64 and 334–343
Vulnerability Type: Unrestricted outbound request and unbounded download
Risk Level: Medium

Vulnerable Code:

python
def download_file(url: str, dest: Path) -> Path:
    """Download a file from URL to dest path."""
    print(f"Downloading {url} ...")
    try:
        r = requests.get(url, stream=True, timeout=60)
        r.raise_for_status()
        with open(dest, "wb") as f:
            for chunk in r.iter_content(chunk_size=8192):
                if chunk:
                    f.write(chunk)
        print(f"Saved to {dest}")
        return dest
    except Exception as e:
        print(f"Error downloading {url}: {e}", file=sys.stderr)
        sys.exit(1)
python
file_path = Path(args.file)
temp_dir = None
is_url = args.file.startswith("http://") or args.file.startswith("https://")

if is_url:
    temp_dir = Path(tempfile.mkdtemp())
    dest = temp_dir / "audio_input"
    # try to keep extension
    ext = Path(args.file).suffix or ".mp3"
    dest = dest.with_suffix(ext)
    download_file(args.file, dest)
    file_path = dest

Technical Analysis

The downloader accepts any URL beginning with http:// or https://. It does not reject loopback, private, link-local, multicast, reserved, or cloud metadata addresses. The requests library follows redirects by default, but redirected destinations are not revalidated.

The streamed response is also written without enforcing a maximum byte count. The timeout limits waiting behavior but does not impose a total response-size limit. Content type and downloaded file structure are not validated before the file is passed to later processing components.

In an agent, shared server, or other remotely influenced execution context, this behavior creates a server-side request forgery primitive and a resource-exhaustion risk.

...[truncated 1294 chars]

Remediation
View remediation

Remediation Suggestions

  • Require explicit confirmation before downloading a user-supplied remote URL.
  • Parse URLs with a standard URL parser and permit only explicitly supported schemes.
  • Resolve the hostname and reject all loopback, private, link-local, multicast, unspecified, and reserved IP ranges.
  • Disable automatic redirects or validate the destination after every redirect.
  • Defend against DNS rebinding by connecting only to the validated resolved address while preserving correct TLS hostname verification.
  • Enforce a conservative maximum response size using both Content-Length and a running byte counter.
  • Set connection and read timeouts separately and impose an overall operation deadline.
  • Restrict accepted media types and validate the downloaded file before passing it to ffmpeg or a transcription provider.
  • Consider an administrator-configurable domain allowlist for server-side deployments.

T08 · Insecure Dependencies

Warning
Location
references/troubleshooting.md:7
Finding

Unpinned and Mutable Dependency Installation Instructions Create Supply-Chain Risk

Content
View full analysis

Vulnerability Details

File Location: references/troubleshooting.md, lines 7–14
Additional Locations: SKILL.md, lines 96–101; references/whisper-models.md, lines 17–21 and 46–50
Vulnerability Type: Unpinned third-party dependencies and mutable source installation
Risk Level: Medium

Vulnerable Code:

bash
pip install openai-whisper
bash
pip install git+https://github.com/openai/whisper.git
bash
pip install torch --index-url https://download.pytorch.org/whl/cu118

Technical Analysis

The installation instructions do not specify reviewed package versions or artifact hashes. The Git-based fallback is especially risky because it installs from a mutable repository reference rather than an immutable commit. The effective code installed by these commands can therefore change after this Skill has been audited.

Python package installation can execute package build hooks and installs executable code that is later imported by the transcription script. A compromised upstream account, repository, package release, package index, or dependency chain could therefore introduce code execution into the environment where users follow these instructions.

This finding concerns unsafe dependency acquisition rather than evidence that the named upstream projects are currently malicious.

Attack Path

  1. A user follows the setup or troubleshooting documentation.
  2. pip resolves the latest available package release, transitive dependencies, or current Git repository state.
  3. An upstream package, repository, release account, or dependency has been compromised or has changed incompatibly since the Skill was reviewed.
  4. Package build or installation code executes under the user's account.
  5. The installed code later executes again when transcribe.py imports Whisper or related components.

Impact Assessment

A compromised dependency can execute with all privileges grant ...[truncated 431 chars]

Remediation
View remediation

Remediation Suggestions

  • Pin each direct dependency to a reviewed, exact version.
  • For Git dependencies, pin a full immutable commit hash rather than a branch or repository head.
  • Maintain a lock file that includes all transitive dependencies and cryptographic hashes.
  • Use pip install --require-hashes -r requirements.txt or an equivalent reproducible dependency-management workflow.
  • Prefer authenticated official package indexes and reviewed binary artifacts over mutable source installations.
  • Install dependencies in a dedicated virtual environment under a non-privileged account.
  • Add a documented update process that reviews release notes, verifies hashes, scans dependencies, and regenerates the lock file.
  • Avoid recommending administrator or root-level package installation.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (13)

Tainted flow: 'headers' from os.environ.get (line 202, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/transcribe.py (reported line 210)May include surrounding context.

python
print(f"Sending {file_path} to Deepgram...")
    try:
        with open(file_path, "rb") as f:
            response = requests.post(url, params=params, headers=headers, data=f, timeout=300)
        response.raise_for_status()
    except requests.exceptions.RequestException as e:
        print(f"Deepgram API error: {e}", file=sys.stderr)

YARA rule 'agent_skill_remote_bootstrap_execution': Remote script or code download followed by execution/bootstrap installation [agent_skills]

High
Category
YARA Match
Confidence
85% confidence
Finding

YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Content

Scanner excerpt · references/troubleshooting.md (reported line 13)May include surrounding context.

Troubleshooting Guide — Voice Transcriber

Common issues and how to fix them.

Installation Issues

whisper module not found

bash
pip install openai-whisper

If that fails, try:

bash
pip install git+https://github.com/openai/whisper.git

ffmpeg not found

  • Windows: Download from https://ffmpeg.org/download.html and add to PATH.
  • macOS: brew install ffmpeg
  • Linux: apt install ffmpeg (Ubuntu/Debian) or yum install ffmpeg (CentOS)

Python version issues

Whisper requires Python 3.8+. Check:

bash
python3 --version

Transcription Errors

RuntimeError: CPU not supported (Apple Silicon)

Use the ARM64 version of Python or install Rosetta 2.

HTTPError 429 (Deepgram rate limit)

You’ve hit the API rate limit. Wait a minute and

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill documents behaviors that require shell, file writes, environment-variable access, and optional network egress, but it declares no explicit tool scope or permission boundaries. In an agent environment, this creates an authorization gap: the agent may invoke broader capabilities than users or orchestrators expect, increasing the chance of unintended file access, command execution, or external data transmission.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
75% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · SKILL.md (reported line 153)May include surrounding context.

md
**This skill does NOT:**
- Store API keys in plain text (use environment variables)
- Auto‑upload without confirmation
- Retain files on external servers after processing

## External Endpoints

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · references/troubleshooting.md (reported line 97)May include surrounding context.

bash
# Create directory with proper permissions
mkdir -p ~/voice-transcriber/transcripts
chmod 755 ~/voice-transcriber/transcripts

Script not executable (Linux/macOS)

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script accepts arbitrary http/https URLs and fetches them server-side, which expands the capability from local transcription into general-purpose network retrieval. In an agent context, this can be abused for SSRF-like behavior against internal services, metadata endpoints, or other network locations reachable from the host running the skill.

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/transcribe.py (reported line 77)May include surrounding context.

python
str(audio_path)
    ]
    try:
        subprocess.run(cmd, check=True, capture_output=True)
        print(f"Extracted audio to {audio_path}")
        return audio_path
    except subprocess.CalledProcessError as e:

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/transcribe.py (reported line 93)May include surrounding context.

python
str(audio_path)
    ]
    try:
        subprocess.run(cmd, check=True, capture_output=True)
        print(f"Extracted audio to {audio_path}")
        return audio_path
    except subprocess.CalledProcessError as e:

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

When the Deepgram provider is selected, the script uploads the full audio content to a third-party service without a strong privacy warning, consent gate, or policy control. Because voice notes often contain sensitive personal or business information, this can create unintended data disclosure in agent deployments where users may assume local-only processing.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% 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 · scripts/transcribe.py (reported line 195)May include surrounding context.

python
print("Error: DEEPGRAM_API_KEY environment variable not set.", file=sys.stderr)
        sys.exit(1)

    url = "https://api.deepgram.com/v1/listen"
    params = {"punctuate": "true", "utterances": "true"}
    if diarize:
        params["diarize"] = "true"

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% 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/transcribe.py (reported line 384)May include surrounding context.

python
# Merge transcripts
    if args.format == "json":
        # For JSON, just concatenate the 'text' fields (simplistic)
        merged = {"text": " ".join([json.loads(p).get("text", "") for p in transcript_parts])}
        final_transcript = json.dumps(merged, ensure_ascii=False, indent=2)
    else:

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
79% confidence
Finding

The privacy section states the skill does not auto-upload without confirmation, yet earlier instructions say URL input should be downloaded to temp and processed automatically. Even though downloading is not the same as uploading, this mismatch can mislead users about network behavior and cause the agent to fetch remote content without an explicit approval step.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

This markdown file includes explicit commands to set DEEPGRAM_API_KEY, which involves handling a sensitive credential. The section provides no warning not to paste real keys into shared terminals, shell history, screenshots, or committed scripts, so users are not informed about the privacy/security implications.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.