T09 · Insecure Skill Coding Practices
Warning
- Location
- lib/tax_calc.py:2165
- Finding
- Spreadsheet Formula Injection in Batch CSV Export## Vulnerability Details **File Location**: `lib/tax_calc.py`, lines 2165-2169 **Vulnerability Type**: CSV/spreadsheet formula injection **Risk Level**: Medium ### Vulnerable Code ```python for emp in batch_result["员工明细"]: csv += f"{emp['姓名']},{emp['月薪']:.2f},{emp['年终奖']:.2f}," csv += f"{emp['年度税前']:.2f},{emp['月度个税']:.2f}," csv += f"{emp['月度到手']:.2f},{emp['年度个税']:.2f}," csv += f"{emp['年度到手']:.2f}\n" ``` ### Technical Analysis The employee name inserted through `emp['姓名']` originates from caller-controlled employee data and is concatenated directly into CSV output. The code performs neither standards-compliant CSV quoting nor spreadsheet formula neutralization. If a name begins with a spreadsheet formula marker such as `=`, `+`, `-`, or `@`, spreadsheet software may interpret the cell as a formula rather than plain text. For example: ```text =HYPERLINK("https://attacker.example","Open") ``` Names containing commas, quotation marks, carriage returns, or newlines can also alter the CSV structure and inject additional cells or rows. ### Attack Path 1. An attacker or untrusted data source supplies an employee record whose `name` starts with a spreadsheet formula marker. 2. `batch_calculate_tax()` copies the supplied name into the batch result under the employee-name field. 3. `generate_batch_excel_data()` concatenates that value directly into the first CSV column. 4. The generated data is saved as a CSV file and opened by an HR or payroll user in spreadsheet software. 5. The spreadsheet application may evaluate the attacker-controlled value as a formula. 6. The formula may display deceptive links, initiate external resource lookups, or perform other actions allowed by the spreadsheet application and its security configuration. ### Impact Assessment Successful exploitation occurs in the context of the user opening the exported CSV, not with the privileges of the Python calculator itself. The potential scope includes: - Execution of attacke ...[truncated 650 chars]
- Remediation
- ## Remediation Suggestions 1. Generate CSV through Python's `csv.writer` rather than manual string concatenation so commas, quotation marks, carriage returns, and newlines are escaped correctly. 2. Treat every user-controlled textual field as potentially formula-bearing. 3. Before writing a text cell, inspect its first non-whitespace character. If it is `=`, `+`, `-`, or `@`, prefix the value with an apostrophe or use another neutralization strategy compatible with the intended spreadsheet software. 4. Preserve the original name separately if exact round-trip fidelity is required, and document any neutralization applied to exported values. 5. Open output streams with `newline=""` and an explicit encoding such as UTF-8 with BOM when compatibility with common spreadsheet applications is required. 6. Add regression tests for names containing formula markers, commas, quotation marks, tabs, carriage returns, and newlines. Example hardening pattern: ```python import csv import io def neutralize_spreadsheet_formula(value: object) -> str: text = str(value) if text.lstrip().startswith(("=", "+", "-", "@")): return "'" + text return text output = io.StringIO(newline="") writer = csv.writer(output) writer.writerow([ "Name", "Monthly Salary", "Bonus", "Annual Gross", "Monthly Tax", "Monthly Net", "Annual Tax", "Annual Net", ]) for emp in batch_result["Employee Details"]: writer.writerow([ neutralize_spreadsheet_formula(emp["Name"]), f"{emp['Monthly Salary']:.2f}", f"{emp['Bonus']:.2f}", f"{emp['Annual Gross']:.2f}", f"{emp['Monthly Tax']:.2f}", f"{emp['Monthly Net']:.2f}", f"{emp['Annual Tax']:.2f}", f"{emp['Annual Net']:.2f}", ]) csv_data = output.getvalue() ``` The field names in the example should be adapted to the application's existing result structure.
