Back to skill

Security audit

unisound-exercise-guidance

Security checks across malware telemetry and agentic risk

Overview

This skill is for rehabilitation guidance, but it expands into remote medical advice generation and broad document processing without clear enough scoping or privacy controls.

Install only if you are comfortable sending rehabilitation exercise details to the listed remote medical-model endpoint and running local document conversion/OCR tools on selected input files. Treat the generated guidance as informational and require clinical review for patient-specific rehabilitation decisions; the publisher should tighten the medical boundary, permissions, privacy disclosure, and fallback import behavior before broad use.

SkillSpector

By NVIDIA
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (19)

subprocess module call

Medium
Category
Dangerous Code Execution
Content
cmd = [tesseract_bin, str(path), "stdout"]
    if lang_arg:
        cmd.extend(["-l", lang_arg])
    proc = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=False)
    if proc.returncode != 0 or not proc.stdout.strip():
        raise PreprocessError(f"Image OCR failed: {proc.stderr.strip() or 'no text returned'}")
    return proc.stdout
Confidence
70% confidence
Finding
proc = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=False)

subprocess module call

Medium
Category
Dangerous Code Execution
Content
def detect_tesseract_langs(tesseract_bin: str) -> Sequence[str]:
    proc = subprocess.run(
        [tesseract_bin, "--list-langs"],
        stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=False,
    )
Confidence
70% confidence
Finding
proc = subprocess.run( [tesseract_bin, "--list-langs"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=False, )

subprocess module call

Medium
Category
Dangerous Code Execution
Content
if not office_bin:
        raise PreprocessError("libreoffice/soffice not found for office document conversion.")
    with tempfile.TemporaryDirectory(prefix="med-skill-preprocess-") as tmp_dir:
        proc = subprocess.run(
            [office_bin, "--headless", "--convert-to", "txt:Text", "--outdir", tmp_dir, str(path)],
            stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=False,
        )
Confidence
70% confidence
Finding
proc = subprocess.run( [office_bin, "--headless", "--convert-to", "txt:Text", "--outdir", tmp_dir, str(path)], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True

subprocess module call

Medium
Category
Dangerous Code Execution
Content
if not office_bin:
        raise PreprocessError("libreoffice/soffice not found for xls conversion.")
    with tempfile.TemporaryDirectory(prefix="med-skill-preprocess-") as tmp_dir:
        proc = subprocess.run(
            [office_bin, "--headless",
             "--convert-to", "csv:Text - txt - csv (StarCalc):44,34,76,1",
             "--outdir", tmp_dir, str(path)],
Confidence
70% confidence
Finding
proc = subprocess.run( [office_bin, "--headless", "--convert-to", "csv:Text - txt - csv (StarCalc):44,34,76,1", "--outdir", tmp_dir, str(path)],

subprocess module call

Medium
Category
Dangerous Code Execution
Content
pass
    pdf_to_text = shutil_which("pdftotext")
    if pdf_to_text:
        proc = subprocess.run(
            [pdf_to_text, "-layout", str(path), "-"],
            stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=False,
        )
Confidence
70% confidence
Finding
proc = subprocess.run( [pdf_to_text, "-layout", str(path), "-"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=False, )

Lp3

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding
Without declared permissions the skill's intent is opaque and cannot be validated.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
描述聚焦于构建病人端术后康复运动指导能力,本身与最终输出方向基本相关;但代码实际包含一个通用文档预处理与多格式解析管道,并依赖外部大模型 API 生成指导内容,而不是单纯实现类似 CareKit instructions task view 的本地指导展示能力。尤其是多格式文件读取/OCR/PDF与Office转换、以及向外部服务发送内容,均未在描述中体现,属于额外能力和资源访问。因此描述不能准确完整代表代码实际行为。

Description-Behavior Mismatch

Medium
Confidence
93% confidence
Finding
The manifest and earlier documentation describe a narrowly scoped guidance skill that takes rehabilitation exercise items and outputs structured instruction for frontend rendering. Later sections broaden the behavior to accept PDFs, Office documents, images with OCR, and to produce large-model 'analysis/reminders', which goes beyond simply displaying existing exercise guidance.

Intent-Code Divergence

Medium
Confidence
96% confidence
Finding
The medical-boundary statement says the skill 'only displays existing exercise guidance', implying a presentation-only function. The output contract then states that the 'text' field is generated by an internal medical large model and contains interpretation/analysis/reminders, which actively contradicts the display-only claim.

Description-Behavior Mismatch

High
Confidence
95% confidence
Finding
The manifest describes a patient-facing rehabilitation exercise guidance skill modeled after CareKit instructions views, which implies presenting or structuring exercise instructions. This file instead implements a broad document-ingestion and text/table extraction tool for PDFs, Office documents, spreadsheets, JSON, CSV, and images, which is semantically different from exercise-guidance functionality.

Context-Inappropriate Capability

High
Confidence
92% confidence
Finding
The code executes LibreOffice/soffice, pdftotext, and tesseract through subprocesses to convert and OCR arbitrary files. Launching external binaries to process arbitrary patient-provided documents is not an obvious requirement for a patient exercise instruction skill and materially expands capability beyond the stated purpose.

Description-Behavior Mismatch

Medium
Confidence
92% confidence
Finding
The manifest describes a postoperative rehabilitation exercise guidance capability, which implies generating guidance content, but the implementation sends the provided exercise, phase, and precaution data to a remote API endpoint for processing. External network transmission is a materially broader behavior than a local guidance renderer and is not disclosed in the manifest description.

Context-Inappropriate Capability

Medium
Confidence
87% confidence
Finding
When preprocessing fails, the skill imports and executes Python code from a filesystem path under '_shared/doc-preprocess' using importlib. Dynamic code loading from another module tree is not an obvious or necessary capability for a patient exercise guidance skill and expands what the skill can do beyond its stated purpose.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The skill documentation states that execution uses an internal medical large-model API and that authentication is provided via `--appkey`, which implies user-provided rehabilitation/medical content will be sent off-box for inference. In this markdown file, there is no explicit warning about remote data transmission, privacy impact, or handling of potentially sensitive health information.

Natural-Language Policy Violations

Medium
Confidence
87% confidence
Finding
The entire skill description and examples are written as Chinese-only patient guidance, and the OCR dependency is explicitly constrained to `chi_sim+eng`, indicating a fixed language/locale assumption. The file does not offer language selection or explain that the skill is intentionally limited to a specific locale or user population.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
This code invokes external binaries such as libreoffice/soffice, pdftotext, and tesseract to process user-supplied files, which is a safety-relevant operation for a preprocessing skill. Although the file has a brief module docstring, there is no confirmation prompt, user-facing log/print, or inline warning near these subprocess executions to disclose that external programs will be run on the user's documents.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The OCR path automatically prefers "chi_sim+eng" when those Tesseract language packs are available, which imposes a locale/language choice in behavior. The file does not offer the user any language selection or opt-in, and the code does not document a justified region-specific constraint.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The script sends exercise name, recovery phase, instructions, frequency, duration, and precautions to a remote HTTPS endpoint via `_call_llm`, but there is no confirmation prompt or user-facing notice at the call site or in the CLI output explaining that input data will be transmitted off-box. For a medical-rehabilitation skill, this is a privacy-relevant network operation that should be explicitly disclosed to users.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The natural-language prompt is entirely written in Chinese and instructs the model to produce markdown rehabilitation guidance in that language, but the file does not provide any user opt-in, locale selection, or documented region-specific justification. This creates a language-policy issue because the skill effectively enforces a specific language by default.

VirusTotal

65/65 vendors flagged this skill as clean.

View on VirusTotal

Static analysis

Detected: suspicious.dynamic_code_execution

Dynamic code execution detected.

Critical
Code
suspicious.dynamic_code_execution
Location
scripts/run.py:194