Back to skill

Security audit

WiseDiag-Report

Security checks for vulnerabilities and agentic risk

Overview

This skill appears purpose-built for WiseDiag medical report interpretation, but it sends sensitive medical files to a cloud API and has under-scoped local output behavior that users should review before installing.

Install only if you trust WiseDiag with the medical reports you provide. Use a temporary environment variable or a dedicated secret manager for the API key, avoid private or signed URLs unless necessary, choose a secure output directory, and avoid custom output names containing path separators or '..' until the filename handling is fixed.

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)

T08 · Insecure Dependencies

Note
Location
requirements.txt:1
Finding

Unpinned Third-Party Dependency Creates a Supply-Chain Risk

Content
View full analysis

Vulnerability Details

File Location: requirements.txt:1
Vulnerability Type: Unbounded dependency resolution without integrity verification
Risk Level: Low

Vulnerable Code

text
requests>=2.28.0

The documented installation process executes:

bash
pip install -r requirements.txt

Technical Analysis

The project specifies only a minimum version of requests. It does not pin an exact reviewed version, impose an upper bound, or provide a cryptographic hash for package integrity verification. Consequently, the package installed at any given time depends on the current state of the configured Python package index and dependency resolver.

This does not demonstrate that the current requests package is malicious. However, it creates a supply-chain weakness because a future compromised release, compromised package index, or maliciously configured package source could provide code that was never reviewed as part of this project.

Python packages and their transitive dependencies execute with the privileges of the Python environment in which they are installed and subsequently imported.

Attack Path

  1. An attacker compromises a future eligible dependency release, a transitive dependency, the configured package index, or the user's package-index configuration.
  2. A user follows the documented installation command.
  3. pip resolves an unreviewed version satisfying requests>=2.28.0.
  4. The compromised package is installed and may execute code during installation or when imported by scripts/report.py.
  5. The malicious code runs with the privileges of the installing or invoking user.

Impact Assessment

Successful exploitation could allow execution of arbitrary Python code in the installation or runtime environment. The resulting access would generally be limited to the privileges of the user or service account performing the installation or running the script. That scop ...[truncated 153 chars]

Remediation
View remediation

Remediation Suggestions

  • Pin requests and all transitive dependencies to reviewed versions in a lock file.
  • Generate and verify SHA-256 hashes, such as by using pip-compile --generate-hashes and installing with pip --require-hashes.
  • Install packages only from an explicitly configured trusted package index.
  • Regularly scan locked dependencies for known vulnerabilities and update them through a controlled review process.
  • Use an isolated virtual environment with minimal operating-system privileges.
  • Avoid relying only on a lower version bound as a security control.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/report.py:227
Finding

Output Filename Path Traversal Allows File Creation Outside the Selected Directory

Content
View full analysis

Vulnerability Details

File Location: scripts/report.py:227-240
Vulnerability Type: Path traversal through an unsanitized output filename
Risk Level: Medium

Vulnerable Code

python
stem = name or f"report_{int(time.time())}"
out_path = out_dir / f"{stem}.md"
if out_path.exists():
    counter = 1
    while (out_dir / f"{stem}_{counter}.md").exists():
        counter += 1
    out_path = out_dir / f"{stem}_{counter}.md"
    print(f"[!] Name conflict, saving as: {out_path.name}")

md = "# Medical Report Interpretation\n\n"
if is_file_mode:
    for i, fp in enumerate(image_sources, 1):
        md += f"**File {i}:** {fp}\n\n"
else:
    for i, url_item in enumerate(image_sources, 1):
        md += f"**Image {i}:** {url_item}\n\n"

The resulting path is later written without containment validation:

python
out_path.write_text(md, encoding="utf-8")

Technical Analysis

The --name argument is described as a filename stem, but its value is used directly in a filesystem path. The code does not reject absolute paths, path separators, or parent-directory components such as ...

A value such as ../../target causes the effective destination to escape the selected output directory. An absolute value can similarly cause pathlib path composition to disregard the preceding output directory. The .md suffix is always appended, but this does not prevent creation of files at unintended writable locations.

The existing-file check prevents direct overwriting: if the target already exists, the program selects a suffixed filename. Nevertheless, it does not prevent unauthorized creation of a new Markdown file outside the intended directory. The destination's parent directory must already exist and be writable.

The written document includes user-supplied paths or URLs, the supplied question, and content returned by the remote API. If another agent or application later treats Markdow ...[truncated 1529 chars]

Remediation
View remediation

Remediation Suggestions

  • Treat --name strictly as a filename stem and reject absolute paths, /, \, . and ...
  • Apply a conservative allowlist, such as ASCII letters, digits, underscores, and hyphens.
  • Resolve the output directory and candidate destination, then verify that the destination remains beneath the resolved output directory.
  • Create files atomically with exclusive creation mode to prevent races and accidental replacement.
  • Consider generating filenames internally rather than accepting arbitrary names.
  • Return an explicit validation error instead of silently normalizing unsafe input.

Example containment approach:

python
import re
from pathlib import Path

if name is not None and not re.fullmatch(r"[A-Za-z0-9_-]+", name):
    raise ValueError("Output name may contain only letters, digits, underscores, and hyphens")

out_dir = Path(output_dir or Path.cwd()).resolve()
out_dir.mkdir(parents=True, exist_ok=True)

stem = name or f"report_{int(time.time())}"
out_path = (out_dir / f"{stem}.md").resolve()

if out_path.parent != out_dir:
    raise ValueError("Output path escapes the selected directory")
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (12)

Tainted flow: 'headers' from os.environ.get (line 107, 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/report.py (reported line 136)May include surrounding context.

python
request_part = ("request", (None, json.dumps(request_data), "application/json"))

        try:
            resp = requests.post(
                url,
                headers=headers,
                files=[request_part] + files_list,

Tainted flow: 'headers' from os.environ.get (line 107, 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/report.py (reported line 172)May include surrounding context.

python
def _stream_response(url, headers, payload, files_arg, image_sources, question, output_dir, name) -> bool:
    """Send JSON request and parse SSE stream."""
    try:
        with requests.post(
            url, headers=headers, json=payload,
            stream=True, timeout=REQUEST_TIMEOUT,
        ) as resp:

Session Persistence

Medium
Category
Rogue Agent
Confidence
90% confidence
Finding

The README recommends persisting the API key by appending it directly to ~/.zshrc, which stores a long-lived secret in plaintext in a shell startup file. This increases the chance of credential exposure through backups, dotfile syncing, accidental sharing, local compromise, or later disclosure by tools that read shell configuration files.

Content

Scanner excerpt · README.md (reported line 30)May include surrounding context.

Temporary (current terminal session)

export WISEDIAG_API_KEY=your_api_key_here

Permanent (add to ~/.zshrc or ~/.bashrc)

echo 'export WISEDIAG_API_KEY=your_api_key_here' >> ~/.zshrc source ~/.zshrc

text

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill declares no explicit tool scope even though it uses environment secrets, network access, and file writing. In an agentic system, missing permission boundaries can let the skill run with broader capabilities than users expect, including transmitting sensitive medical files and writing output locally without a clearly declared trust boundary.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The activation phrases are broad enough to match ordinary health-related requests, which increases the chance the skill is invoked automatically when the user did not specifically intend to send private documents to a third-party cloud service. In this context, accidental activation is more dangerous because the skill processes highly sensitive medical data and can upload local files or URLs externally.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This code file contains natural-language strings that assume Chinese as the interaction language, including the example question and the default prompt used when no question is supplied. The policy forbids forcing a specific language without user opt-in, and the script does not present any language-selection option or justification for the locale constraint.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
95% confidence
Finding

The skill transmits user-supplied medical report URLs and accompanying prompts to an external third-party service for analysis. In the context of medical report interpretation, this is sensitive health data handling and creates real confidentiality and compliance risk if users are not clearly informed, if URLs contain private tokens, or if the external processor is not explicitly trusted and governed.

Content

Scanner excerpt · scripts/report.py (reported line 172)May include surrounding context.

python
def _stream_response(url, headers, payload, files_arg, image_sources, question, output_dir, name) -> bool:
    """Send JSON request and parse SSE stream."""
    try:
        with requests.post(
            url, headers=headers, json=payload,
            stream=True, timeout=REQUEST_TIMEOUT,
        ) as resp:

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

The example command uses a Chinese question string ("请解读异常指标") even though the rest of the README is in English, which can imply a preferred or required language without explicit user opt-in. The documented policy requires flagging language or locale constraints when the skill does not clearly offer a language choice or justify the locale specificity.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
76% confidence
Finding

The phrase "or similar requests (in any language)" is a natural-language policy statement about language handling, but it does not frame this as a user choice or opt-in. Under the language/locale policy rule, forcing or presuming multilingual handling without explicit user selection can be a policy concern.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
97% confidence
Finding

The dependency is specified as requests>=2.28.0, which allows future versions to be installed without review and does not guarantee a known-safe, reproducible build. In a medical-report interpretation skill that may fetch remote image URLs and process sensitive data, dependency drift can unexpectedly introduce vulnerable or incompatible releases into production.

Content

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

text
requests>=2.28.0

Unverifiable Dependency: requests has 16 known advisory(ies) (CVE-2014-1830 (Exposure of Sensitive Information to an Unauthorized Actor in Requests); CVE-2024-47081 (Requests vulnerable to .netrc credentials leak via malicious URLs); CVE-2024-35195 (Requests `Session` object does not verify requests after making first request wi) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
92% confidence
Finding

Because requests is not pinned, it is impossible to verify whether the deployed version includes fixes for known advisories affecting the library. This is more concerning in this skill's context because it may retrieve user-supplied image URLs, making request-handling flaws such as credential leakage, redirect issues, or other client-side request vulnerabilities more relevant.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

The script persists highly sensitive medical content, OCR output, and model interpretation to a Markdown file on local disk by default, even though the skill description emphasizes interpretation of provided reports rather than long-term storage. In a medical context, this materially increases privacy risk because PHI may be written to shared directories, backed up, indexed, or accessed by other local users/processes without the user's explicit consent.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.