T09 · Insecure Skill Coding Practices
- Location
scripts/decor_qty.py:990- Finding
Untrusted CAD-Derived Text Is Written as an Active Spreadsheet Formula
- Content
View full analysis
Vulnerability Details
File Location:
scripts/cad_measure_to_input.py:92-108, 272-275;scripts/decor_qty.py:619-639, 990-996
Vulnerability Type: Spreadsheet formula injection
Risk Level: MediumTechnical Analysis
Text originating from CAD measurement JSON is inserted into output records without neutralizing spreadsheet formula prefixes. For example, the measurement
formulaandreview_reasonfields are incorporated into the说明column:python if value is None: detail = ( f"未换算:图面值 {fmt(row.get('value_drawing_units'))} {row.get('drawing_unit') or ''};" f"{row.get('review_reason') or '缺比例或单位'}" ) else: detail = f"{row.get('formula') or ''};{row.get('review_reason') or ''}".strip(";") output = blank() output.update({ "楼层": floor, "区域": zone, "房间": room_name(row), "部位类型": "待确认-面积" if kind == "area" else "待确认-长度", "做法名称": "CAD识图测量候选(需绑定做法)", "做法类型": "通用", "间数": "1", "说明": f"{detail};final_quantity=false", "依据": f"cad-file-reader:{row.get('source_schema') or ''}:{row.get('source_id') or ''}", "需核对": "是", })These values are written directly to CSV:
python target.parent.mkdir(parents=True, exist_ok=True) with target.open("w", encoding="utf-8-sig", newline="") as handle: writer = csv.DictWriter(handle, fieldnames=HEADERS) writer.writeheader() writer.writerows(rows)When this generated CSV is subsequently processed by
decor_qty.py, externally derived fields such as说明,依据, room names, and node information remain strings in the calculation result:python result: dict[str, Any] = { "行号": int(source_line) if source_line is not None else row_index + 2, "楼层": _text(row.get("楼层")), "区域": _text(row.get("区域")), "房间": _text(row.get("房间")), "房间类型": _text(row.get("房间类型")), "部位类型": part, "做法编号": code, "做法名称": _text(row.get("做法名 ...[truncated 3144 chars]- Remediation
View remediation
Remediation Suggestions
-
Introduce one centralized sanitizer for all text written to CSV or XLSX:
python def spreadsheet_safe(value: Any) -> Any: if not isinstance(value, str): return value if value.startswith(("=", "+", "-", "@")): return "'" + value return value -
Apply the sanitizer to every externally derived text value before calling
csv.DictWriter.writerows()orWorksheet.append(). -
For XLSX output, explicitly store untrusted values as literal strings rather than formulas. Do not rely solely on visual formatting or cell number formats.
-
Preserve numeric values as numeric types and sanitize only text fields, so quantity calculations and report formatting remain functional.
-
Apply protection at the final output boundary even if earlier import stages also sanitize data. This prevents project-rule files, manually edited CSV files, or future import paths from bypassing the protection.
-
Add regression tests covering values beginning with
=,+,-, and@in CAD formula, review-reason, room, source-ID, node, description, and basis fields. Verify that generated XLSX cells are stored as literal strings and have a non-formula data type. -
Document that imported CAD metadata is treated as untrusted data and must never be interpreted as spreadsheet syntax.
-
