Back to skill

Security audit

med-record-gen

Security checks for vulnerabilities and agentic risk

Overview

This medical-record skill performs the advertised task, but it sends raw doctor-patient dialogue to an external API despite promising de-identification first.

Review this carefully before installing, especially for real patient data. Use it only if you are comfortable sending the selected dialogue text to the external backend, or require the publisher to add local de-identification, an explicit consent prompt, endpoint disclosure, and tests proving identifiers are not transmitted.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/gen_initial_record.py:22
Finding

Raw Medical Dialogue Is Transmitted Without Promised De-identification

Content
View full analysis

Vulnerability Details

File Location: scripts/gen_initial_record.py:22-26, 80-84
Related Documentation: SKILL.md:32-34
Vulnerability Type: Sensitive medical information disclosure caused by missing de-identification controls
Risk Level: High

Vulnerable Code

python
payload = {
    "diag_id": diag_id,
    "dep_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
    "diag": dialogue,
}
try:
    data_bytes = json.dumps(payload, ensure_ascii=False).encode("utf-8")
python
with open(input_path, "r", encoding="utf-8") as f:
    dialogue_text = f.read()

print(f"Generating initial visit record from dialogue: {input_path}")
# Directly call the medical-record generation API
record_text = call_record_api(
    diag_id=diag_id,
    dialogue=dialogue_text,
    timeout=timeout,
)

The request is subsequently transmitted to the fixed external endpoint through urllib.request.urlopen() at scripts/gen_initial_record.py:35-37.

Technical Analysis

The skill documentation states at SKILL.md:32-34 that personally identifiable information will be removed before content is sent to any model or API. It specifically identifies names, identity numbers, phone numbers, detailed addresses, and similar information as data that will be de-identified.

The implementation does not enforce this guarantee. It reads the complete dialogue file into dialogue_text, passes that string unchanged to call_record_api(), assigns it directly to the outbound diag property, and sends the resulting JSON to:

text
https://shangbao.yunzhisheng.cn/skills/record-gen/gen_record_by_diag_v1

No local redaction, identifier detection, data minimization, user confirmation, or residual-sensitive-data validation occurs before transmission. HTTPS protects data in transit but does not prevent the receiving service from accessing the raw medical dialogue.

Because doctor-patient dialogue may contain both health information and direct identifiers, the missing ...[truncated 1734 chars]

Remediation
View remediation

Remediation Suggestions

  1. Implement local de-identification before constructing the outbound payload. At minimum, detect and replace names, phone numbers, identity numbers, email addresses, detailed addresses, and other direct identifiers.
  2. Treat de-identification as a mandatory security boundary rather than an optional preprocessing step. Do not send the request if sanitization fails or if high-confidence identifiers remain.
  3. Use a structured pipeline in which only the sanitized value can be passed to call_record_api(); avoid retaining an API that accepts arbitrary raw dialogue.
  4. Add automated tests that intercept outbound requests and verify that representative identifiers never appear in the request body.
  5. Obtain explicit informed consent before transmitting medical data to the external service, and clearly identify the recipient, purpose, retention policy, and applicable data-handling terms.
  6. Minimize metadata by validating whether diag_id and the precise timestamp are necessary. Use a non-identifying, per-request random identifier when correlation is not required.
  7. Apply a finite, secure default network timeout instead of waiting indefinitely.
  8. Update SKILL.md so its privacy claims precisely match the implemented and independently verified controls.
  9. Consider processing the dialogue locally when privacy requirements prohibit third-party disclosure.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (5)

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The code transmits full medical dialogue content, including potentially regulated personal health information, to an external backend. Even though the endpoint uses HTTPS, this is still a high-risk data exfiltration path if users are not informed, if the service is not strictly necessary, or if retention/access controls are unclear.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill documentation indicates capabilities for file read, file write, and network access, but it does not declare any explicit tool scope or permissions boundary. In a medical-record generation context handling sensitive patient dialogue, this creates a real least-privilege and transparency gap: operators and users cannot verify whether filesystem and network use are restricted to the minimum necessary, increasing the risk of unintended data access or exfiltration.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The description states the skill generates records from '中文医患对话文本', which constrains use to Chinese and presents the language requirement as fixed behavior rather than an optional or user-selected locale. Under the policy, forcing a specific language without opt-in is a natural-language locale violation unless clearly documented as a justified region-specific tool.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill advertises record generation from local dialogue text, but the implementation sends the full doctor-patient conversation to a remote API for processing. In a medical context, this is sensitive health data, so undisclosed off-host transmission materially changes the trust and privacy boundary and can violate user expectations or compliance requirements.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The CLI reports that it is generating a record from a local file but does not warn the operator that the contents will be uploaded to a remote backend. In a healthcare workflow, lack of a prominent disclosure increases the chance of accidental disclosure of sensitive patient information.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.