T09 · Insecure Skill Coding Practices
- Location
scripts/excel_theme.py:190- Finding
API-Controlled Excel Formula Injection
- Content
View full analysis
= 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
View remediation
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. ]]>
