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## 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
## 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## 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
## 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## 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
## 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.

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.

Description-Behavior Mismatch

High
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.

Context-Inappropriate Capability

High
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.

Lp3

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.

Missing User Warnings

Medium
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.

Context-Inappropriate Capability

Medium
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.

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
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.

Missing User Warnings

Medium
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.

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
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.

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
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.

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
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

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
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Natural-Language Policy Violations

Medium
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.

Description-Behavior Mismatch

Medium
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.

Missing User Warnings

Medium
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.

Natural-Language Policy Violations

Low
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.

Natural-Language Policy Violations

Low
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.

Intent-Code Divergence

Low
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.

Static analysis

Detected: suspicious.dynamic_code_execution

Dynamic code execution detected.

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