T09 · Insecure Skill Coding Practices
Warning
- Location
- finance_agent.py:42
- Finding
- Spreadsheet Formula Injection in CSV Reports## Vulnerability Details **File Location**: `finance_agent.py`, lines 42-48; CSV generation at lines 72-73; file export at lines 91-93 **Vulnerability Type**: CSV formula injection **Risk Level**: Medium ### Vulnerable Code ```python self.expenses.append( { "Date": date, "Category": category, "Amount": amount, "Description": description, } ) ``` ```python if output_format == "csv": return df.to_csv(index=False) ``` ```python if data: with open(output_path, "w") as f: f.write(data) ``` ### Technical Analysis The `category` and `description` parameters are accepted without validation or output neutralization. The `amount` parameter can also contain an unexpected string because Python type annotations do not enforce runtime types. These values are passed directly to Pandas and serialized into CSV output. CSV escaping protects the file structure but does not neutralize spreadsheet formulas. If an attacker supplies a value beginning with a formula indicator such as `=`, `+`, `-`, or `@`, spreadsheet applications may interpret the cell as a formula when a user opens the exported report. A malicious description could, for example, contain a spreadsheet formula that creates an external hyperlink, performs an external data request in supporting software, or misrepresents financial values. The exact result depends on the spreadsheet application and its security configuration. ### Attack Path 1. An attacker or untrusted user submits an expense with a formula-prefixed `category`, `description`, or improperly typed `amount`. 2. `add_expense()` stores the supplied value without neutralizing spreadsheet control characters. 3. `_save_expenses()` or `generate_expense_table("csv")` serializes the malicious value into CSV. 4. `export_report()` writes the generated content to a report file. 5. A finance employee opens that CSV file in spreadsheet softw ...[truncated 947 chars]
- Remediation
- ## Remediation Suggestions 1. Validate all parameters at runtime rather than relying only on type annotations: - Require `category` and `description` to be strings. - Parse `amount` as a finite decimal value. - Reject NaN, infinity, and unexpected object types. 2. Before spreadsheet-oriented CSV export, neutralize text cells whose first non-whitespace character is `=`, `+`, `-`, or `@`. 3. Prefix dangerous text values with an apostrophe or apply another neutralization strategy compatible with the intended spreadsheet clients. 4. Apply neutralization only to spreadsheet export copies if exact raw values must be retained internally. 5. Document whether generated CSV files are intended for spreadsheet use. 6. Add tests covering formula-prefixed values, leading whitespace, tabs, carriage returns, and all user-controlled fields. 7. Consider generating a format with explicit cell typing, while still applying appropriate protections for that format. Example defensive helper: ```python def spreadsheet_safe(value): if isinstance(value, str): normalized = value.lstrip() if normalized.startswith(("=", "+", "-", "@")): return "'" + value return value safe_df = df.map(spreadsheet_safe) return safe_df.to_csv(index=False) ```
