T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/excel_theme.py:190
- Finding
- API-Controlled Excel Formula Injection<![CDATA[ ## Vulnerability Details **File Location**: `scripts/excel_theme.py`, lines 190–195 and 264–266 **Vulnerability Type**: Spreadsheet formula injection **Risk Level**: Medium ### Vulnerable Code ```python cell_value = value # A列=公司名称,B列=股票代码;从C列开始尝试转数字。 if col_idx >= 3: cell_value = _coerce_numeric(value) cell = ws.cell(row=current_row, column=col_idx, value=cell_value) if col_idx >= 3 and isinstance(cell_value, (int, float)): num_fmt = _thousand_number_format_from_raw(value) ``` API-provided title fields are also written directly: ```python ws.cell(row=1, column=1, value=title) ws.cell(row=2, column=1, value=input_title) ws.cell(row=3, column=1, value=frontend_title) ``` ### Technical Analysis The workbook content originates from the remote comparable-company API. API-controlled table values and title fields are passed directly to `openpyxl` cells without neutralizing spreadsheet formula prefixes. `openpyxl` treats strings beginning with `=` as formulas. The first two table columns bypass `_coerce_numeric()` entirely, while later columns preserve values that cannot be converted to numbers. Consequently, an API response containing a value such as `=HYPERLINK(...)` can be stored as an executable spreadsheet formula rather than literal text. Values beginning with `+`, `-`, or `@` may also receive formula-like treatment in some spreadsheet applications and should be considered unsafe. The remote API request itself is consistent with the Skill's declared functionality: `scripts/get_data.py` sends the user-supplied company query and `EM_API_KEY` over HTTPS to the documented Eastmoney endpoint. No unrelated environment variables, local files, or system information were observed being transmitted. The security issue is therefore not the necessary network operation, but the lack of a trust-boundary check when remote response data is converted into an Excel workbook. ### Attack Path 1. An attacker compromises, manipulates, or otherwise control ...[truncated 1643 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Introduce a centralized function that converts all untrusted strings into literal spreadsheet text before writing them to cells: ```python def _safe_excel_value(value: Any) -> Any: if not isinstance(value, str): return value # Preserve the displayed content while preventing formula interpretation. if value.startswith(("=", "+", "-", "@")): return "'" + value return value ``` 2. Apply this function to every API-derived string, including table cells and title fields: ```python cell_value = value if col_idx >= 3: cell_value = _coerce_numeric(value) cell_value = _safe_excel_value(cell_value) cell = ws.cell(row=current_row, column=col_idx, value=cell_value) ``` ```python ws.cell(row=1, column=1, value=_safe_excel_value(title)) ws.cell(row=2, column=1, value=_safe_excel_value(input_title)) ws.cell(row=3, column=1, value=_safe_excel_value(frontend_title)) ``` 3. Where values are semantically identifiers, such as company names and stock codes, explicitly set the cells to text and do not permit formula interpretation. 4. Validate the API response against a strict schema. Enforce expected types, maximum lengths, and permitted formats for titles, company names, stock codes, and numeric metrics. 5. Add regression tests using values beginning with `=`, `+`, `-`, and `@`. Reopen generated workbooks with `openpyxl` and confirm that the resulting cells contain literal text rather than formulas. 6. Continue using HTTPS for the declared API request, and restrict authentication headers to the documented Eastmoney endpoint. Avoid following redirects to untrusted hosts with the API key attached. ]]>
