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