Back to skill

Security audit

unisound-glucose-monitor-record

Security checks for vulnerabilities and agentic risk

Overview

This skill is not clearly malicious, but it handles sensitive blood-glucose health data with mandatory external AI analysis and several under-scoped runtime risks users should review carefully.

Install only if you are comfortable sending patient glucose records and any notes to the listed external medical-model API. Avoid putting names, identifiers, or extra medical details in notes, prefer JSON/CSV input over document or image uploads, rotate any appkey used on the command line, and review whether your environment requires explicit health-data consent, retention, and compliance 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 (3)

other

Error
Location
scripts/run.py:15
Finding

Mandatory Disclosure of Sensitive Health Records to an External API

Content
View full analysis

Vulnerability Details

File Location: scripts/run.py, lines 15, 31-48, and 153-164
Vulnerability Type: Sensitive health data disclosure
Risk Level: High

Vulnerable Code

python
API_URL = "https://maas-api.hivoice.cn/v1/chat/completions"
MODEL = "u2-med"
python
def _call_llm(system_prompt: str, user_prompt: str, appkey: str) -> str:
    payload = {
        "model": MODEL,
        "temperature": 0.0,
        "messages": [
            {"role": "system", "content": system_prompt},
            {"role": "user", "content": user_prompt},
        ],
    }
    try:
        req = Request(API_URL, data=json.dumps(payload, ensure_ascii=False).encode("utf-8"),
                      headers={"Content-Type": "application/json",
                               "Authorization": f"Bearer {appkey}"})
        resp = urlopen(req, timeout=120)
        body = json.loads(resp.read().decode("utf-8"))
    except HTTPError as exc:
        detail = exc.read().decode("utf-8", errors="replace")[:500]
        raise RuntimeError(f"API HTTP {exc.code}: {detail}")
    except URLError as exc:
        raise RuntimeError(f"API unreachable: {exc.reason}")
    if "choices" not in body or not body["choices"]:
        raise RuntimeError("API response missing choices")
    return body["choices"][0].get("message", {}).get("content", "")
python
def build(data: Dict[str, Any], appkey: str) -> Dict[str, Any]:
    # 1. Local preprocessing: normalize record list
    raw = data if isinstance(data, list) else [data]
    records = _local_normalize(raw)

    # 2. Validate required fields
    for i, rec in enumerate(records):
        require(rec, "value")

    # 3. Construct user prompt
    user_prompt = f"Please analyze the following blood glucose monitoring data:\n```json\n{json.dumps(records, ensure_ascii=False, indent=2)}\n```"

    # 4. Call API
    text = _call_llm(SYSTEM_PROMPT, us
...[truncated 1826 chars]
Remediation
View remediation

Remediation Suggestions

  • Require explicit, informed user consent before transmitting health records.
  • Clearly identify the external processor and disclose its retention, training, and secondary-use policies.
  • Minimize transmitted data by omitting timestamps and notes unless they are necessary for the requested analysis.
  • Redact names, patient identifiers, contact details, and other identifying information before creating the prompt.
  • Add a local-only mode that produces structured records without invoking the external API.
  • Provide a preview of the exact payload and destination before transmission.
  • Establish appropriate encryption, data-processing, retention, deletion, and audit controls for sensitive medical information.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/run.py:287
Finding

API Credential Exposed Through Command-Line Arguments

Content
View full analysis

Vulnerability Details

File Location: scripts/run.py, line 287; documented usage in SKILL.md, line 72
Vulnerability Type: Command-line secret exposure
Risk Level: Medium

Vulnerable Code

python
parser.add_argument("--appkey", required=True, help="Internal medical LLM authentication key (required)")

The documented invocation requires the key directly on the command line:

bash
python3 scripts/run.py --input input.json --output output.json --appkey YOUR_KEY

Technical Analysis

Authentication secrets passed as command-line arguments can be exposed outside the intended process. Depending on the operating environment, command arguments may be visible in process listings, shell history, job-control interfaces, diagnostic reports, CI/CD logs, telemetry, or wrapper scripts.

Although the key is subsequently used in an HTTPS authorization header, transport security does not protect it from local disclosure before the request is sent.

Attack Path

  1. A user follows the documented command and supplies a real API key through --appkey.
  2. The shell may persist the complete command in its history.
  3. While the process is running, another local user or monitoring service may inspect its arguments.
  4. Alternatively, a CI/CD runner or wrapper may record the command in execution logs.
  5. The observer extracts the key and uses it to authenticate unauthorized API requests.

Impact Assessment

An attacker who obtains the key can make requests with the victim's API identity, consume assigned quota, incur costs, or access capabilities associated with that credential. The exact scope depends on the server-side privileges assigned to the key.

This issue does not independently provide local privilege escalation, but disclosure can compromise the associated remote account or service authorization.

Remediation
View remediation

Remediation Suggestions

  • Read the credential from a protected environment variable or platform secret manager.
  • Support reading the credential from standard input without terminal echo.
  • If a credential file is supported, require restrictive file permissions and reject insecure ownership or modes.
  • Remove command-line secret usage from the documented quick-start example.
  • Ensure logs and exception handlers never include authorization headers or credential values.
  • Use short-lived, narrowly scoped credentials and provide a straightforward rotation and revocation process.

T08 · Insecure Dependencies

Warning
Location
scripts/run.py:305
Finding

Preprocessing Failure Executes an Unverified Python Module Outside the Skill

Content
View full analysis

Vulnerability Details

File Location: scripts/run.py, lines 305-315
Vulnerability Type: Unverified external dependency execution
Risk Level: Medium

Vulnerable Code

python
except PreprocessError as exc:
    # Fall back to _shared/doc-preprocess
    try:
        _shared_dir = Path(__file__).resolve().parent.parents[3] / "_shared" / "doc-preprocess" / "scripts"
        if not _shared_dir.exists():
            print(f"ERROR: Unable to read input; local preprocessing failed and _shared/doc-preprocess is unavailable. Cause: {exc}", file=sys.stderr)
            return 1
        import importlib.util as _iu
        _spec = _iu.spec_from_file_location("_shared_preprocess", _shared_dir / "preprocess.py")
        _sp = _iu.module_from_spec(_spec)
        _spec.loader.exec_module(_sp)
        input_type = _sp.detect_input_type(input_path, args.input_type)

Technical Analysis

When local preprocessing raises PreprocessError, the application constructs a path outside the skill directory and dynamically executes _shared/doc-preprocess/scripts/preprocess.py using exec_module().

Python module loading executes all top-level statements in the selected file. The code performs no cryptographic integrity verification, version pinning, trusted-root validation, or ownership and permission checks before execution. Consequently, the effective code executed by the skill is not limited to the audited package.

This is a conditional execution path rather than remote payload retrieval: exploitation requires the attacker to be able to create or modify the expected shared file on the local filesystem.

Attack Path

  1. An attacker with write access to the expected shared dependency path creates or modifies _shared/doc-preprocess/scripts/preprocess.py.
  2. The attacker places arbitrary Python statements at module scope.
  3. The skill is invoked with an input that causes the bundled preprocessor to rai ...[truncated 877 chars]
Remediation
View remediation

Remediation Suggestions

  • Remove the dynamic fallback and fail closed when the bundled preprocessor cannot handle an input.
  • Prefer packaging all required preprocessing code inside the reviewed skill or importing a pinned, normally installed dependency.
  • If the shared module is operationally required, validate it against a trusted cryptographic digest before import.
  • Resolve the path and verify that it remains beneath an explicitly configured trusted root.
  • Verify secure ownership and permissions for the module and all parent directories.
  • Pin and record the expected shared dependency version.
  • Avoid exec_module() for dependencies selected through filesystem layout alone.
  • Run document preprocessing in a sandbox with minimal filesystem, credential, and network access.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (19)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The skill is presented as a record-keeping tool, but it also transmits patient glucose data to an external/internal model API and generates medical interpretation, risk prompts, and advice. In a healthcare setting, this is a material behavior change: sensitive health data leaves the local boundary and the tool begins influencing care decisions despite being framed as basic logging.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The skill is presented as a record-keeping tool, but it also transmits patient glucose data to an external/internal model API and generates medical interpretation, risk prompts, and advice. In a healthcare setting, this is a material behavior change: sensitive health data leaves the local boundary and the tool begins influencing care decisions despite being framed as basic logging.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The file implements a broad document-ingestion pipeline for PDFs, Office files, spreadsheets, JSON, text, and images, which materially exceeds the declared scope of a blood-glucose record skill. Capability overreach increases attack surface, complicates review, and can indicate an unsafe supply-chain or hidden-feature risk even if each component is not individually malicious.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The code sends blood glucose records and related notes to an external API endpoint using the provided appkey, which is a real data exfiltration path for sensitive medical information. Because the skill is framed as basic chronic disease record management, this network transfer is not obviously necessary or adequately justified, increasing privacy, compliance, and trust risks.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding

The skill declares broad capabilities in practice—network access, shell use, file read/write, and environment access—without any explicit tool-scope restrictions in the manifest. In a medical-record skill, this increases the risk of unintended data exfiltration or unsafe file/command handling because operators and users cannot clearly see or constrain what the skill is allowed to do.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill text states that execution is forced through a medical model API, but it does not provide a clear user-facing warning in the main description that structured glucose data and generated interpretation will be sent off-box. For health data, lack of transparent disclosure undermines informed consent and can lead to privacy, compliance, and trust failures.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

Invoking LibreOffice, pdftotext, and tesseract adds powerful external-processing capabilities that are hard to justify for a basic patient glucose logging skill. In this context, the mismatch makes the feature set more dangerous because it enables parsing of many untrusted complex formats that should not be necessary.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
78% confidence
Finding

Although the subprocess is not shell-injected, the code sends user-supplied office documents to LibreOffice for conversion. External document converters have a long history of parser vulnerabilities, so this expands the attack surface significantly for a skill whose stated purpose is simple glucose-record handling.

Content

Scanner excerpt · scripts/preprocess.py (reported line 111)May include surrounding context.

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

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This code invokes external binaries via subprocess to process user-supplied documents, including LibreOffice conversion and later similar calls for PDF/OCR handling. While the operations are part of preprocessing, there is no confirmation prompt, print/log statement, or comment/docstring near these calls disclosing that external tools will be executed on the user's files.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
78% confidence
Finding

This invokes LibreOffice on untrusted .xls input, exposing the host to risks in complex legacy document parsing. The danger is not command injection but unsafe processing of attacker-controlled files by a heavyweight external application.

Content

Scanner excerpt · scripts/preprocess.py (reported line 126)May include surrounding context.

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

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
73% confidence
Finding

The code passes untrusted PDFs to an external pdftotext binary. PDF parsing is a common source of denial-of-service and memory-corruption issues, so invoking an external parser on arbitrary uploads increases exposure beyond the skill's apparent business need.

Content

Scanner excerpt · scripts/preprocess.py (reported line 153)May include surrounding context.

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

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

python
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

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

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

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

Natural-language strings throughout the file, including the system prompt and CLI descriptions, are written entirely in Chinese and instruct Chinese output for patients. There is no opt-in, language selection mechanism, or documented justification that this skill is intentionally restricted to a Chinese-language context.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill metadata and implementation are misaligned: it presents itself as a blood glucose record-keeping capability, but it also performs remote AI analysis, risk classification, trend inference, and advice generation on patient data. In a medical context, this hidden expansion of scope is dangerous because users and integrators may not realize sensitive health data is being used for secondary processing by an external model service.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The build path packages patient glucose records and sends them for AI analysis without any explicit disclosure, confirmation, or privacy notice in the tool flow. In a healthcare context, silent transmission of sensitive medical data to a third-party endpoint materially increases privacy, regulatory, and patient-safety risk, especially if users assume this is a local record tool.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
80% confidence
Finding

The documentation specifies tesseract with chi_sim+eng, which imposes a Chinese-language OCR configuration as part of the skill behavior. The file does not offer a language choice or explain that the locale restriction is optional or region-specific, so it can violate language/locale policy expectations.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
75% confidence
Finding

The top-level docstring is written as a Chinese-only description and, combined with the hardcoded OCR language preference later in the file, indicates a default Chinese-language orientation without any visible user choice or opt-in. This can violate language/locale policy when a skill imposes a locale implicitly rather than offering selection.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
98% confidence
Finding

The top-level docstring explicitly states the skill is self-contained and independent of _shared. However, the exception fallback path imports and executes preprocess.py from _shared/doc-preprocess, which directly contradicts that documentation claim.

Content

No source excerpt is available for this finding.