Back to skill

Security audit

unisound-blood-pressure-monitor-record

Security checks for vulnerabilities and agentic risk

Overview

This blood-pressure skill processes sensitive health records through an external medical model and broad file parsers, so it should be reviewed carefully before use.

Install only if users explicitly understand that blood-pressure records and notes may be sent to the listed external medical model. Avoid putting names, diagnoses, contact details, or other identifiers in notes, prefer JSON or CSV input, avoid untrusted documents/images, and use a safer secret mechanism than command-line app keys if available.

Vulnerability Patterns
  • Tool Hijacking and SpoofingModifies or replaces tools so legitimate-looking calls execute attacker logic
  • 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 (4)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/run.py:27
Finding

Transmission of Sensitive Health Records to an External Model API Without Data-Minimization Controls

Content
View full analysis
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: raise RuntimeError(f"API HTTP {exc.code}") except URLError as exc: raise RuntimeError(f"API unreachable: {exc.reason}") return body["choices"][0]["message"]["content"] ``` ```python def build(data: Dict[str, Any], appkey: str) -> Dict[str, Any]: raw = data if isinstance(data, list) else [data] records = [] for r in raw: records.append({ "systolic": require(r, "systolic"), "diastolic": require(r, "diastolic"), "heart_rate": r.get("heart_rate", ""), "unit": r.get("unit", "mmHg"), "measured_at": r.get("measured_at", ""), "note": r.get("note", ""), }) user_prompt = f"请分析以下血压监测数据:\n```json\n{json.dumps(records, ensure_ascii=False, indent=2)}\n```" text = _call_llm(SYSTEM_PROMPT, user_prompt, appkey) return { "skill": "血压监测记录", "status": "ok", "data": {"record_type": "blood_pressure", "record_count": len(records), "records": records}, "text": text.strip(), } ``` ### Technical Analysis The implementation serializes every parsed blood-pressure record and sends it to the fixed external endpoint `https://maas-api.hivoice.cn/ ...[truncated 1544 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/run.py:180
Finding

Bearer Credential Exposed Through Command-Line Arguments

Content
View full analysis
Remediation
View remediation

T07 · Tool Hijacking and Spoofing

Warning
Location
scripts/run.py:207
Finding

Execution of an Unverified Python Module Outside the Audited Skill Directory

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/run.py:72
Finding

Missing Type and Range Validation for Patient-Facing Clinical Measurements

Content
View full analysis
Dict[str, Any]: raw = data if isinstance(data, list) else [data] records = [] for r in raw: records.append({ "systolic": require(r, "systolic"), "diastolic": require(r, "diastolic"), "heart_rate": r.get("heart_rate", ""), "unit": r.get("unit", "mmHg"), "measured_at": r.get("measured_at", ""), "note": r.get("note", ""), }) user_prompt = f"请分析以下血压监测数据:\n```json\n{json.dumps(records, ensure_ascii=False, indent=2)}\n```" text = _call_llm(SYSTEM_PROMPT, user_prompt, appkey) return { "skill": "血压监测记录", "status": "ok", "data": {"record_type": "blood_pressure", "record_count": len(records), "records": records}, "text": text.strip(), } ``` ### Technical Analysis The `require()` check only rejects missing or empty systolic and diastolic fields. It does not ensure that these values are numeric, finite, within plausible bounds, expressed in the expected unit, or clinically consistent. Heart rate, timestamps, and units are also accepted without schema validation. Malformed strings, negative numbers, extreme values, unsupported units, and inconsistent measurements can therefore reach the remote model. The result is still returned with `"status": "ok"`, which can make an interpretation based on invalid data appear successfully validated. This is primarily an integrity and patient-safety weakness rather than a route to operating-system compromise. ### Attack Path 1. A user, faulty OCR process, or malicious input source supplies nonnumeric, implausible, or incorrectly labeled pressure values. 2. The fields pass the presence-only checks. 3. The invalid values are serialized a ...[truncated 635 chars]
Remediation
View remediation
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
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (21)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The skill presents itself as basic record-keeping but also performs remote API calls to an external medical LLM endpoint and generates medical analysis or reminders. In a healthcare context, undisclosed outbound transmission of vitals and notes is especially sensitive because it can expose protected health data and create reliance on AI-generated medical guidance beyond the stated scope.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The skill presents itself as basic record-keeping but also performs remote API calls to an external medical LLM endpoint and generates medical analysis or reminders. In a healthcare context, undisclosed outbound transmission of vitals and notes is especially sensitive because it can expose protected health data and create reliance on AI-generated medical guidance beyond the stated scope.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The file implements a broad, generic ingestion pipeline for documents, spreadsheets, JSON, PDFs, and images, which does not align with a blood-pressure monitoring record skill. This mismatch matters because unnecessary capability broadening increases attack surface, enables processing of far more attacker-controlled content than required, and can facilitate data exfiltration or exploitation through unrelated parsers.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill documents capabilities implying file access, shell execution, environment access, and network use, but declares no explicit tool scope or permission boundaries. In a health-data context, this increases the risk of overbroad execution and accidental exposure of sensitive patient information through unnecessary capabilities or unsafe runtime defaults.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill states it does not diagnose or replace a doctor, but elsewhere says it provides medical interpretation, analysis, and reminders. This contradiction is dangerous because disclaimers do not eliminate the practical effect of delivering health guidance, and users may rely on the output while believing the feature is only a neutral recorder.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The documentation says the skill is only for blood-pressure recording, yet the output specification includes medical interpretation, analysis, and reminders generated by an internal LLM. This creates a security and safety issue because users may unknowingly submit health data for remote inference and may treat generated content as medically authoritative despite the stated boundary.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill mandates use of a remote medical LLM API but does not prominently warn users that sensitive health data may be transmitted off-box. In this context, the omission is significant because blood pressure values, timestamps, and notes are medical data, and users need clear notice and consent before remote processing.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

OCR plus Office/PDF conversion adds heavyweight parsing and execution dependencies that are not justified by the stated patient blood-pressure recording function. In this context, that unnecessary capability makes the skill more dangerous because attackers can supply crafted files to exercise complex external tools that the skill does not need.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
71% confidence
Finding

Although shell injection is avoided by using an argument list, this code sends untrusted office documents to LibreOffice for conversion. Parsing attacker-controlled DOC files with large, complex external converters expands the attack surface and can enable denial of service or exploitation of vulnerabilities in the external tool, especially in an agent skill that need not process arbitrary office documents for blood-pressure logging.

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

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
72% confidence
Finding

This subprocess invokes LibreOffice on untrusted XLS files, which creates risk from complex file parsing in a powerful third-party application. Even without shell injection, hostile spreadsheet files can trigger resource exhaustion or exploit parser bugs, and this capability is broader than expected for a blood-pressure record skill.

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
70% confidence
Finding

Passing attacker-supplied PDFs to external text-extraction utilities increases exposure to vulnerabilities in those tools and can also cause resource exhaustion on malformed or oversized files. The absence of shell invocation reduces injection risk, but the file-parsing attack surface remains significant, particularly because generic PDF ingestion is not clearly justified by the skill purpose.

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

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill transmits structured blood pressure readings and related health metadata to an external LLM service, which is a real privacy and data-governance risk for medical information. In a patient-facing chronic disease context, even seemingly simple vitals can be sensitive health data, and the code provides no minimization, consent flow, retention controls, or assurance that external processing is appropriate for protected medical data.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The prompt directs the model to perform guideline-based classification, trend analysis, abnormality flagging, risk prompts, and lifestyle recommendations, which goes beyond simple recordkeeping into medical advice generation. In a blood-pressure management skill, this increases safety risk because incorrect, hallucinated, or overconfident advice may influence patient behavior without clinician oversight.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

Medical data is embedded into the LLM prompt and sent off-box without any user-visible warning, confirmation, or opt-in. In a healthcare skill handling patient vitals, silent external disclosure is especially dangerous because users may reasonably expect local record processing rather than transmission to a remote AI provider.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The code forwards user-supplied notes and measurement fields verbatim into the external prompt, which can include highly sensitive personal health information and free-text identifiers. Because those values are later used to generate output, private content may be unnecessarily exposed to the remote provider and potentially echoed back in responses or logs.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

Adding PDF, Office document, and image OCR ingestion to a basic blood-pressure logging skill unnecessarily broadens the attack surface and encourages processing of unrelated sensitive documents. While not inherently malicious, this creates avoidable exposure to parser, conversion, and OCR tool risks and makes the skill more capable than its narrow medical-record purpose requires.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

The dependency list specifies tesseract with chi_sim+eng, which imposes a specific language configuration for OCR. The document does not indicate that users can choose other OCR languages or that the restriction is optional, creating a language/locale policy concern.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The only user-facing natural-language description in this file is written in Chinese, which implicitly fixes the skill description to a specific language. There is no accompanying opt-in, multilingual alternative, or documented reason that this skill is intentionally region- or language-specific.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

The system prompt explicitly requires output aimed at patients in Chinese, and the overall skill text and interface are Chinese-specific. There is no indication in this file that users may select another language or opt into this locale constraint.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.dynamic_code_execution

Dynamic code execution detected.

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