Back to skill

Security audit

TCM Clinic - English Edition

Security checks for vulnerabilities and agentic risk

Overview

This clinic-management skill is coherent, but it handles patient health and billing records with weak privacy safeguards.

Review carefully before installing. Use only on a secured, single-user machine or protected clinic environment, keep the data directory out of shared, synced, public, or source-controlled folders, and assume the Excel files and command output may contain sensitive patient health and billing information. Do not use it for real regulated clinical records unless you add appropriate privacy, access-control, encryption, retention, backup, and spreadsheet-formula sanitization safeguards.

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

Warning
Location
scripts/clinic_manager.py:120
Finding
Spreadsheet Formula Injection Through Untrusted Cell Values<![CDATA[ ## Vulnerability Details **File Location**: `scripts/clinic_manager.py:120-125` **Vulnerability Type**: Spreadsheet formula injection **Risk Level**: Medium ### Vulnerable Code ```python def append_row(data_dir: str, module: str, row_data: dict): schema = SCHEMAS[module] filepath = get_data_path(data_dir, module) wb, ws = load_workbook_safe(filepath, schema["sheet"], schema["headers"]) row_values = [row_data.get(h, "") for h in schema["headers"]] ws.append(row_values) wb.save(filepath) ``` User-controlled values reaching this function are assembled in multiple command handlers, including patient fields at `scripts/clinic_manager.py:180-191`: ```python row = { "patient_id": generate_id("P", data_dir, "patients"), "name": name, "gender": args.gender or "", "birth_date": args.birth_date or "", "age": args.age or 0, "phone": args.phone or "", "address": args.address or "", "constitution_type": args.constitution or "", "allergies": args.allergies or "", "chronic_diseases": args.chronic_diseases or "", "notes": args.notes or "", "created_date": get_today(), "last_visit_date": "", } ``` The same vulnerable data flow affects medical-record fields, herb fields, appointment fields, and financial fields. ### Technical Analysis The application copies untrusted CLI strings directly into Excel cells through `openpyxl` without validating or neutralizing spreadsheet formula prefixes. A value beginning with `=`, `+`, `-`, or `@` may be interpreted as a formula when the generated workbook is opened in spreadsheet software. For example, an attacker could provide a formula-prefixed patient name, supplier, diagnosis, prescription, purpose, or notes field. The value would be stored as active spreadsheet content instead of literal text. Depending on the spreadsheet application, platform, and security configuration, malicious formulas can initiate external requests, expose workbook or envir ...[truncated 1768 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Introduce a centralized cell-sanitization function and apply it to every string before calling `ws.append`. 2. Treat strings beginning with `=`, `+`, `-`, or `@` as untrusted formula content. 3. Either reject such input or force it to be stored as literal text, for example: ```python FORMULA_PREFIXES = ("=", "+", "-", "@") def sanitize_excel_value(value): if isinstance(value, str) and value.startswith(FORMULA_PREFIXES): return "'" + value return value row_values = [ sanitize_excel_value(row_data.get(header, "")) for header in schema["headers"] ] ws.append(row_values) ``` 4. Consider stripping leading control characters, tabs, carriage returns, and line feeds before checking the first significant character, because spreadsheet import behavior can vary. 5. Validate structured fields such as dates, IDs, phone numbers, numeric amounts, and enum values rather than treating every value as unrestricted text. 6. Add automated tests covering every CLI-controlled text field and all recognized formula prefixes. 7. Document that previously generated workbooks may contain unsafe cells and should be inspected or migrated through a sanitization routine. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/clinic_manager.py:40
Finding
Sensitive Patient and Medical Data Stored in Unencrypted Excel Files<![CDATA[ ## Vulnerability Details **File Location**: `scripts/clinic_manager.py:40-85` and `scripts/clinic_manager.py:96-105` **Vulnerability Type**: Plaintext storage of sensitive health and personal data **Risk Level**: Medium ### Vulnerable Code The schemas explicitly include personally identifiable information and sensitive medical information: ```python SCHEMAS = { "patients": { "filename": "patients.xlsx", "sheet": "patients", "headers": [ "patient_id", "name", "gender", "birth_date", "age", "phone", "address", "constitution_type", "allergies", "chronic_diseases", "notes", "created_date", "last_visit_date" ], }, "records": { "filename": "medical_records.xlsx", "sheet": "records", "headers": [ "record_id", "patient_id", "patient_name", "visit_date", "chief_complaint", "tongue_condition", "pulse_condition", "observation", "listening_smelling", "inquiry", "diagnosis", "prescription", "advice", "visit_count", "notes" ], }, "herbs": { "filename": "herbs_inventory.xlsx", "sheet": "herbs", "headers": [ "herb_id", "name", "pinyin", "specification", "stock_quantity", "unit", "purchase_price", "retail_price", "supplier", "expiry_date", "entry_date", "minimum_stock", "category", "notes" ], }, "appointments": { "filename": "appointments.xlsx", "sheet": "appointments", "headers": [ "appointment_id", "patient_id", "patient_name", "appointment_date", "time_slot", "status", "purpose", "queue_number", "notes" ], }, "finances": { "filename": "finances.xlsx", "sheet": "finances", "headers": [ "finance_id", "record_id", "patient_id", "patient_name", "date", "type", "amount", "payment_method", "notes" ...[truncated 3033 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Store clinical data in a user-private application data directory rather than the arbitrary current working directory. 2. Create directories and files with owner-only permissions where supported, such as directory mode `0700` and file mode `0600`. 3. Verify existing directory and file permissions before reading or writing data, and warn or refuse operation when they are accessible to unintended users. 4. Use an encrypted database or encrypted container for patient and medical records. Protect encryption keys through the operating system's credential store rather than embedding them in source code. 5. If Excel export is required, make it an explicit operation that produces a temporary or password-protected export, and securely remove temporary plaintext files when they are no longer needed. 6. Warn users not to place the data directory in shared, public, source-controlled, or automatically synchronized locations. 7. Implement backup guidance that preserves encryption and access restrictions. 8. Minimize retained information and support secure record archival and deletion according to applicable clinical-data retention requirements. 9. Document that the application handles sensitive health information and that operators are responsible for applicable privacy and healthcare regulations. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Rogue AgentSelf-Modification, Session Persistence
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (9)

Missing User Warnings

High
Confidence
97% confidence
Finding
The medical-record creation flow prints the complete clinical record to stdout, including complaint, diagnostic observations, diagnosis, prescription, and notes. Because this is highly sensitive health data, exposing it in console output can leak PHI through terminal visibility, job runners, transcript logs, or agent/tool logging systems; the clinic context makes this especially dangerous.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The README explicitly positions the skill to collect, manage, and store highly sensitive health and billing data, and states that all data is stored as local Excel files without any warning about privacy, access controls, encryption, or operational safeguards. In a medical context, this can lead users to handle protected health information insecurely, increasing the risk of unauthorized disclosure, accidental sharing, device compromise, or regulatory noncompliance.

Session Persistence

Medium
Category
Rogue Agent
Content
```
User Request
├── Patient-related? → Patient Management Module
│   ├── "new patient" / "register patient" → Create patient record
│   ├── "find patient" / "search patient" → Search by name/phone/ID
│   ├── "update patient" → Update patient record
│   └── "patient list" / "all patients" → Output patient summary
Confidence
88% confidence
Finding
The skill is designed to create, search, update, and list persistent patient records and related clinic data stored in local Excel files, which is session persistence involving highly sensitive health and financial information. Without explicit safeguards for consent, access control, minimization, retention, and secure storage, this creates a meaningful privacy and confidentiality risk; the medical context makes it more dangerous because the persisted data includes patient identities, diagnoses, prescriptions, appointments, and billing records.

Natural-Language Policy Violations

Medium
Confidence
89% confidence
Finding
Line L180 instructs the skill to 'Use TCM professional terminology in conversation' unconditionally. This imposes a specific language/style constraint on all users without offering a choice or opt-in, which matches the policy's language/locale-style violation criteria.

Missing User Warnings

Medium
Confidence
86% confidence
Finding
This markdown file describes storage of patient identities, medical records, appointments, and financial data in local Excel files, but it provides no warning about the sensitive nature of this information or the need to protect it. Under the markdown-file criteria, descriptions that could affect user data or privacy should include warnings when handling medical and financial records.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The script stores patient demographics, medical records, prescriptions, appointments, and financial data in unencrypted local Excel files. In a clinic-management context this is protected health information and personal data, so local persistence without access controls, encryption, retention notice, or consent handling materially increases confidentiality and compliance risk if the host is shared, compromised, backed up insecurely, or the files are exfiltrated.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
After registration, the program prints the full patient record as formatted JSON to stdout, including contact details, address, allergies, chronic diseases, and notes. Terminal output is often logged, captured in shell history tooling, or visible to nearby users, so this creates an avoidable disclosure channel for sensitive personal and medical information.

Natural-Language Policy Violations

Low
Confidence
71% confidence
Finding
The document defines user-facing categorical values such as gender, constitution types, appointment statuses, and payment methods exclusively in English, with no indication that localization is optional or configurable. This can violate language/locale policy when a skill implicitly forces one language without user opt-in or documented justification.

Natural-Language Policy Violations

Low
Confidence
83% confidence
Finding
All help text, prompts, and operational messages in this clinic management tool are fixed in English, and there is no option for locale or language selection. Under the stated policy, forcing a specific language without user opt-in is a natural-language policy concern.

Static analysis

No suspicious patterns detected.