Back to skill

Security audit

Family Medical History / 家庭医疗档案

Security checks for vulnerabilities and agentic risk

Overview

This skill is for family medical records and mostly matches that purpose, but it stores and exports very sensitive health and identity data without protective defaults and has an export path weakness that can overwrite Markdown files outside its records folder.

Install only if you are comfortable storing family medical and identity information locally in plaintext. Keep the workspace private, avoid cloud-synced or shared folders, do not commit generated databases or Markdown exports, and treat sync_db.py as risky until identifiers are validated and export paths are contained to the records directory.

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 (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/sync_db.py:20
Finding

Path Traversal Allows Arbitrary Markdown File and Directory Writes

Content
View full analysis
dict: """Ensure all subdirectories exist for a member, return base path.""" base = os.path.join(RECORDS_DIR, member_code) for subdir in ["visits", "medications", "exams", "daily_vitals", "attachments"]: os.makedirs(os.path.join(base, subdir), exist_ok=True) os.makedirs(os.path.join(base, "attachments", "2026"), exist_ok=True) os.makedirs(os.path.join(base, "attachments", "2027"), exist_ok=True) return base ``` ```python for row in members: r = dict(zip(cols, row)) base = ensure_dirs(r["member_code"]) profile_path = os.path.join(base, "profile.md") ``` ```python base = ensure_dirs(member_code) visits_dir = os.path.join(base, "visits") for row in visits: v = dict(zip(cols, row)) visit_path = os.path.join(visits_dir, f"{v['visit_id']}.md") # Content generation omitted here; the destination is opened in # destructive write mode. with open(visit_path, "w", encoding="utf-8") as f: f.write(content) ``` ```python base = ensure_dirs(member_code) meds_dir = os.path.join(base, "medications") for row in meds: m = dict(zip(cols, row)) med_path = os.path.join(meds_dir, f"{m['medication_id']}.md") # Content generation omitted here; the destination is opened in # destructive write mode. with open(med_path, "w", encoding="utf-8") as f: f.write(content) ``` ### Technical Analysis The exporter treats database-controlled `member_code`, `visit_id`, and `medication_id` values as trusted filesystem path components. It does not reject absolute paths, path separators, or parent-directory components such as `..`. Python's `os.path.join()` does not enforc ...[truncated 2367 chars]
Remediation
View remediation
str: if not isinstance(value, str) or not SAFE_ID.fullmatch(value): raise ValueError(f"Unsafe {field}") return value ``` 2. Canonicalize every destination and verify that it remains under the intended export root: ```python from pathlib import Path EXPORT_ROOT = Path(RECORDS_DIR).resolve() def contained_path(*parts: str) -> Path: destination = EXPORT_ROOT.joinpath(*parts).resolve() if destination != EXPORT_ROOT and EXPORT_ROOT not in destination.parents: raise ValueError("Export path escapes the records directory") return destination ``` 3. Validate `member_code`, `visit_id`, and `medication_id` independently. Reject absolute paths, `.` or `..` components, path separators, null bytes, and platform-specific alternate separators. 4. Add equivalent constraints at the data-entry boundary and, where practical, SQLite `CHECK` constraints so unsafe identifiers cannot enter the database. 5. Avoid silently overwriting existing files. Use exclusive creation (`"x"`) by default, or require an explicit overwrite option. For legitimate replacement, write to a safe temporary file in the same directory and atomically replace the destination. 6. Run the exporter as an unprivileged account with write access limited to the intended export directory. 7. Add regression tests covering absolute paths, nested traversal, mixed separators, symbolic links, and crafted identifiers imported from legacy records. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/init_db.py:31
Finding

Sensitive Medical and Identity Data Is Stored and Exported Without Enforced Access Protection

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (14)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill clearly handles highly sensitive family medical data and instructs agents to store and update it directly in a local SQLite database, but the description does not explicitly warn users about this persistence behavior. This creates a meaningful privacy and consent risk because users may provide PHI/medical details without realizing they are being durably stored and later queryable.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The templates explicitly solicit highly sensitive personal and medical data, including ID numbers, insurance information, allergies, diagnoses, medications, and hospital record numbers, but provide no privacy notice, data minimization guidance, access control expectations, or safe storage instructions. In a reusable skill/template context, this can normalize insecure collection and local storage of protected health information, increasing the risk of privacy breaches, identity theft, and harmful disclosure of medical conditions.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The module-level docstring describes a read/query helper for the medical records database, implying read-oriented behavior. However, require_db at L26-L40 launches init_db.py, which creates and initializes the database, introducing side effects that contradict the stated query-only intent.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

This module handles family medical records and exposes them through a CLI without any access control, redaction, consent check, or even a privacy warning. In the context of highly sensitive health data, easy command-line listing of members, visits, and medications increases the risk of unauthorized disclosure, especially if the skill is invoked by other agents or on shared systems.

Content

No source excerpt is available for this finding.

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

python
if not os.path.exists(path):
        print("[INFO] Database not found. Initializing...")
        script_dir = os.path.dirname(os.path.abspath(__file__))
        result = subprocess.run(
            ["python3", os.path.join(script_dir, "init_db.py")],
            capture_output=True, text=True
        )

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The generated profile content is hard-coded in Chinese, including headings and field labels, with no indication that language is configurable or intentionally region-scoped. This creates a natural-language locale constraint that is imposed on all users without opt-in.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

This code writes Markdown files containing highly sensitive personal and medical information such as ID numbers, insurance numbers, diagnoses, medications, and emergency contacts. Although the module docstring says it syncs DB content to .md files, it does not warn the user that protected health information will be materialized onto disk in a separate directory structure.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The visit Markdown template uses Chinese-only headings and labels, which imposes a specific language policy on generated content. There is no mechanism for users to choose another language and no documentation that this is a region-specific tool.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The visit sync operation exports encounter dates, institutions, doctors, complaints, illness history, diagnoses, and advice into Markdown files. The script provides success logs after completion, but there is no prior or inline warning that this operation copies sensitive health data from the database into file-based records.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The medication export template is written primarily in Chinese and does not offer users a language or locale option. Under the policy, forcing a specific language without opt-in is a natural-language policy violation unless the locale restriction is clearly justified.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This write operation exports detailed medication and adherence data, including drug names, dosing plans, adverse reactions, and discontinuation reasons, into Markdown files. The code lacks any explicit warning that sensitive treatment information is being persisted outside the database.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

This markdown file includes natural-language guidance that fixes some labels to English values such as "Active", "Resolved", and "Chronic" while the surrounding documentation is primarily Chinese. Because the file does not offer a user language/locale option or explain that English labels are required for interoperability, it may violate the language/locale policy criterion.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The natural-language content of the templates is presented in Chinese, and the file does not indicate that this language requirement is optional or region-specific. Under SQP-3, forcing a specific language without user opt-in can violate language or locale policy expectations.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

This code defines a database schema using mixed-language natural-language labels such as the Chinese identifier on L42 and additional Chinese enum/comment text elsewhere. Because the file does not document a locale-specific requirement or offer any language choice, it can violate a language/locale policy that expects skills to avoid forcing a specific language implicitly.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.