Back to skill

Security audit

Voice To Protocol Transcriber

Security checks for vulnerabilities and agentic risk

Overview

The skill appears to be a local experiment-note logger, but its documentation and install steps do not match the implementation and its file-write scope is weakly controlled.

Review this skill before installing. Treat it as a text-based local protocol logger unless the publisher updates the implementation, avoid installing the listed unnecessary dependencies, use a dedicated save directory, and do not pass untrusted experiment names or sensitive lab/clinical notes without confirming storage and retention controls.

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 (2)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/main.py:152
Finding

Experiment Name Allows Output Path Traversal

Content
View full analysis

Vulnerability Details

File Location: scripts/main.py:152-166
Vulnerability Type: Unrestricted output path construction
Risk Level: Medium

Vulnerable Code

python
def save(self) -> str:
    """保存实验记录"""
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    filename_base = f"{self.experiment_name.replace(' ', '_')}_{timestamp}"
    
    if self.output_format == "markdown":
        file_path = self.save_directory / f"{filename_base}.md"
        self._save_markdown(file_path)
    elif self.output_format == "json":
        file_path = self.save_directory / f"{filename_base}.json"
        self._save_json(file_path)
    elif self.output_format == "txt":
        file_path = self.save_directory / f"{filename_base}.txt"
        self._save_text(file_path)

The resulting path is subsequently opened for writing, for example:

python
with open(file_path, 'w', encoding='utf-8') as f:

Technical Analysis

experiment_name is supplied through the --experiment command-line argument and is incorporated into the output path after replacing spaces only. Path separators, absolute paths, drive prefixes, and .. traversal components are not rejected.

When an absolute child path is combined with a pathlib.Path, the absolute path takes precedence over self.save_directory. Relative traversal components can similarly escape the configured directory after path resolution. The application then opens the resulting file in write mode, creating it or truncating an existing file if its generated name already exists.

The timestamp and fixed extension limit the attacker to generated filenames ending in _<timestamp>.md, _<timestamp>.json, or _<timestamp>.txt; therefore, this does not generally permit overwriting an arbitrary exact filename. It nevertheless violates the intended output-directory boundary.

Attack Path

  1. An attacker or untrusted caller controls the `--exper ...[truncated 1526 chars]
Remediation
View remediation

Remediation Suggestions

  • Treat the experiment name as a display value rather than a filesystem path.
  • Derive a safe filename using an allowlist, such as ASCII letters, digits, hyphens, and underscores.
  • Explicitly reject /, \, absolute paths, drive prefixes, null bytes, and .. path components.
  • Resolve both the save directory and destination, then verify containment before opening the file.
  • Create files using exclusive creation where overwriting is unnecessary.
  • Apply a conservative maximum filename length.

Example containment pattern:

python
import re

root = self.save_directory.resolve()
safe_name = re.sub(r"[^A-Za-z0-9_-]", "_", self.experiment_name)
safe_name = safe_name.strip("_")[:100] or "unnamed_experiment"

filename = f"{safe_name}_{timestamp}.{extension}"
destination = (root / filename).resolve()

if root not in destination.parents:
    raise ValueError("Output path escapes the configured save directory")

Where supported, open the destination with exclusive creation mode ("x") to avoid silently truncating an existing output file.

T08 · Insecure Dependencies

Warning
Location
requirements.txt:1
Finding

Unnecessary Unpinned Packages Create Supply-Chain Exposure

Content
View full analysis

Vulnerability Details

File Location: requirements.txt:1-3
Vulnerability Type: Unpinned and unnecessary third-party dependencies
Risk Level: Medium

Vulnerable Code

text
dataclasses
enum
wave

The project documentation directs users to install this file:

bash
pip install -r requirements.txt

Technical Analysis

The listed names correspond to functionality already supplied by the Python standard library used by scripts/main.py. No version constraints or integrity hashes are specified. Consequently, following the installation instructions asks the package installer to resolve and install externally published packages that the implementation does not need.

Python package installation can execute package build hooks or setup logic. Unnecessary resolution from a public or otherwise untrusted package index therefore expands the supply-chain attack surface and makes installations non-reproducible.

This finding does not establish that the currently published packages are malicious. The vulnerability is the project's unnecessary reliance on unresolved, unpinned package names and its instruction to install them.

Attack Path

  1. A user follows the prerequisite documented in SKILL.md and runs pip install -r requirements.txt.
  2. Pip resolves dataclasses, enum, and wave from the configured package index or mirror.
  3. The selected versions are not constrained or authenticated by hashes in this project.
  4. If a resolved distribution or configured package source is compromised, substituted, or malicious, its installation or build hooks execute with the privileges of the user running pip.
  5. The malicious package can then perform actions available to that user before the skill itself is launched.

Exploitation therefore depends on compromise or malicious substitution in the configured dependency source; no such compromise was demonstrated in the audited files.

Impact

...[truncated 721 chars]

Remediation
View remediation

Remediation Suggestions

  • Remove dataclasses, enum, and wave from requirements.txt when using a supported Python version because the implementation imports the standard-library modules.
  • Declare and enforce the minimum supported Python version.
  • Keep requirements.txt empty if no external runtime dependencies are required.
  • If third-party packages are introduced later, pin exact reviewed versions and use cryptographic hashes.
  • Install from a trusted, controlled package index and review transitive dependencies.
  • Generate reproducible lock files and regularly scan dependencies for known vulnerabilities.
  • Reconcile SKILL.md with the actual implementation; it currently advertises SpeechRecognition, PyAudio, pydub, and python-docx even though the script provides text-only input and does not use those packages.
Vulnerability Patterns
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • 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 (11)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The documented behavior claims real-time voice transcription, but the described implementation does not substantiate actual voice handling while still enabling local file output to user-controlled directories. This mismatch is dangerous because users may trust the declared purpose while the skill performs broader filesystem actions than transparently disclosed.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill documents file read/write behavior but does not declare any tool scope or permissions boundaries. This creates an authorization gap where the runtime may permit filesystem access without explicit user awareness, increasing the risk of unintended writes to sensitive locations.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

A tool that continuously captures spoken laboratory content can collect sensitive research data, personal conversations, or regulated information, yet the skill omits a clear privacy warning. In a lab context, silent recording and persistent storage materially increase confidentiality and compliance risks.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
81% confidence
Finding

The documented default configuration hard-codes the language to "zh-CN" and sets all voice commands to Chinese phrases, which imposes a specific locale by default. Although an English CLI example exists later, the primary configuration does not present locale choice as an explicit user opt-in or explain why Chinese is the required default.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The security section claims no external API calls and restricted output, but the skill references speech recognition that commonly relies on network services and configures storage under the user's home directory. False security claims can mislead users into exposing sensitive experimental audio or notes under weaker controls than expected.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The module docstring says this tool records experimental steps and observations through voice commands, and the CLI description also presents it as a voice recording assistant. In practice, main() always calls start_listening_text(), whose implementation reads typed input from stdin; the code does not perform voice listening despite the active claims in documentation.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The manifest describes recording procedures and observations via voice commands with real-time transcription, and the module/docstrings reinforce that framing. However, the executable path starts a text-input loop using input() and processes typed commands only; there is no microphone handling, speech recognition, or audio transcription logic anywhere in the file.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
60% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

Scanner excerpt · requirements.txt (reported line 1)May include surrounding context.

text
dataclasses
enum
wave

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
60% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

Scanner excerpt · requirements.txt (reported line 2)May include surrounding context.

text
dataclasses
enum
wave

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
60% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

Scanner excerpt · requirements.txt (reported line 3)May include surrounding context.

text
dataclasses
enum
wave

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The code sets the default language to "zh-CN", and surrounding user-facing strings and command phrases are also Chinese-centric. This can amount to a language/locale policy issue because the skill effectively assumes a specific locale unless the user explicitly overrides it.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.