T09 · Insecure Skill Coding Practices
Warning
- Location
- generator.py:493
- Finding
- Spreadsheet Formula Injection in CSV Exports<![CDATA[ ## Vulnerability Details **File Location**: `generator.py:493-500`, with attacker-controlled input originating at `generator.py:517-529` **Vulnerability Type**: CSV formula injection **Risk Level**: Medium ### Vulnerable Code ```python if output_format == "csv": rows = [["产品名称", "平台", "标题", "详情描述"]] for name, results in all_results: for pid, data in results.items(): rows.append([name, data["label"], data["title"], data["description"]]) output = io.StringIO() writer = csv.writer(output) writer.writerows(rows) ``` The exported product name originates from CSV input without formula neutralization: ```python def parse_csv_input(csv_text: str) -> List[Dict]: """解析 CSV 输入,返回产品字典列表""" reader = csv.DictReader(io.StringIO(csv_text.strip())) products = [] for row in reader: products.append({ "product_name": row.get("product_name") or row.get("产品名称") or "", "category": row.get("category") or row.get("类目") or "", "keywords": row.get("keywords") or row.get("关键词") or "", "brand": row.get("brand") or row.get("品牌") or "", "price": row.get("price") or row.get("价格") or "", }) return [p for p in products if p["product_name"]] ``` ### Technical Analysis The application accepts arbitrary product data from an imported CSV and writes that data back into generated CSV output. The standard `csv.writer` correctly quotes CSV syntax but does not prevent spreadsheet applications from interpreting a cell as a formula. A product name beginning with `=`, `+`, `-`, or `@` can therefore remain executable spreadsheet content. Leading tabs, carriage returns, or whitespace may also be used to bypass simplistic prefix checks in some spreadsheet applications. For example, a malicious input product name could contain a formula that initiates an external request when the generated file is opened. The generated description and title fields also incorpo ...[truncated 1510 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Neutralize every untrusted CSV cell before passing it to `csv.writer`. 2. Treat cells beginning with `=`, `+`, `-`, or `@` as dangerous, including values where these characters follow whitespace, tabs, or carriage returns. 3. Prefix dangerous cells with a single quote or use another spreadsheet-safe export convention appropriate to supported spreadsheet applications. 4. Apply protection to product names, titles, descriptions, bullet points, brands, categories, keywords, and all future user-controlled columns. 5. Keep `csv.writer` for structural escaping; formula neutralization is an additional and separate control. 6. Add regression tests for all recognized formula prefixes and whitespace-based bypasses. Example hardening function: ```python def neutralize_csv_cell(value) -> str: text = str(value) normalized = text.lstrip(" \t\r\n") if normalized.startswith(("=", "+", "-", "@")): return "'" + text return text ``` Apply it to each exported value: ```python writer.writerows( [[neutralize_csv_cell(cell) for cell in row] for row in rows] ) ``` ]]>
