T09 · Insecure Skill Coding Practices
- Location
scripts/scrape_page.py:113- Finding
Spreadsheet Formula Injection in CSV and XLSX Exports
- Content
View full analysis
Vulnerability Details
File Location:
scripts/scrape_page.py, lines 113–117 and 135–136
Vulnerability Type: Spreadsheet formula injection
Risk Level: MediumVulnerable Code
python fieldnames = list(data_list[0].keys()) with open(output_path, 'w', encoding='utf-8', newline='') as f: writer = csv.DictWriter(f, fieldnames=fieldnames) writer.writeheader() writer.writerows(data_list)python # Data rows for item in data_list: ws.append([item.get(h, '') for h in headers])Technical Analysis
Data extracted from arbitrary websites is stored in
data_listand written directly into CSV or XLSX cells without neutralizing spreadsheet formula prefixes. A malicious website can supply a scraped value beginning with characters interpreted by spreadsheet applications as formulas, including=,+,-, or@. Tabs and carriage returns may also be relevant formula-triggering prefixes in some spreadsheet applications.The CSV writer correctly handles delimiters and quoting, but CSV quoting does not prevent spreadsheet software from evaluating cell contents as formulas. In the XLSX branch,
openpyxlcan serialize a string beginning with=as a formula cell rather than literal text.Attack Path
- An attacker publishes content on a page that the user is expected to scrape.
- The attacker places a formula-like string in a selected field, such as a title, price, or description.
agent-browserextracts the attacker-controlled text.scrape_page()stores the value in the result dictionary without spreadsheet-safe encoding.save_data()passes the value directly tocsv.DictWriter.writerows()oropenpyxl'sws.append().- The user opens the generated CSV or XLSX file in spreadsheet software.
- Depending on the spreadsheet application and its security configuration, the formula may be evaluated or may prompt the user to enable external content.
...[truncated 743 chars]
- Remediation
View remediation
Remediation Suggestions
Treat all scraped values as untrusted before exporting them to spreadsheet-compatible formats.
- Create a centralized sanitization function that converts values to strings and detects formula-triggering prefixes after accounting for leading tabs, carriage returns, and similar whitespace.
- For CSV output, prefix formula-like values with a single apostrophe so spreadsheet applications treat them as literal text. Apply this transformation to both field names and cell values.
- For XLSX output, create cells explicitly as string cells and store sanitized literal values rather than allowing
openpyxlto infer formula types. - Consider offering a strict export mode that rejects formula-like values instead of modifying them.
- Document that exports contain untrusted website content and should not be opened with active content enabled.
- Add regression tests for values beginning with
=,+,-,@, tab, and carriage return, including values with leading whitespace and quoted CSV fields. - Verify the generated XLSX package to ensure attacker-controlled values are represented as strings rather than formula elements.
Example defensive helper:
python def spreadsheet_safe(value): if value is None: return "" value = str(value) probe = value.lstrip("\t\r") if probe.startswith(("=", "+", "-", "@")): return "'" + value return valueApply the helper to every header and data value before calling
writerows()orws.append().
