T09 · Insecure Skill Coding Practices
- Location
scripts/gmaps_leads_export.py:45- Finding
Spreadsheet Formula Injection in CSV and XLSX Exports
- Content
View full analysis
Vulnerability Details
File Location:
scripts/gmaps_leads_export.py, lines 45–50, 63–69, and 96–112
Vulnerability Type: Spreadsheet formula injection
Risk Level: MediumVulnerable Code
python for r in rows: ws.append([r.get(h, "") for h in headers])python with out_path.open("w", newline="", encoding="utf-8") as f: w = csv.DictWriter(f, fieldnames=headers) w.writeheader() w.writerows(rows)python name = pl.get("name", "") website = d.get("website", "") rows.append( { "name": name, "address": d.get("formatted_address") or pl.get("formatted_address", ""), "phone": d.get("formatted_phone_number") or d.get("international_phone_number", ""), "website": website, "email": "", # website crawl optional step; keep empty by default "rating": d.get("rating") if d.get("rating") is not None else pl.get("rating", ""), "place_id": pid, "google_maps_url": f"https://www.google.com/maps/search/?api=1&query={quote_plus(name)}&query_place_id={pid}", } )Technical Analysis
Business names, addresses, phone numbers, websites, ratings, and place identifiers are obtained from external MCP/Google Maps responses. The script writes these values directly to CSV or XLSX cells without neutralizing spreadsheet formula prefixes.
Values beginning with characters such as
=,+,-, or@may be interpreted as formulas when the export is opened in spreadsheet software. In XLSX output,openpyxlcan store a string beginning with=as a formula rather than literal text. CSV applications may similarly evaluate formula-like fields when opening the file.Consequently, an attacker who can influence a Google Maps listing field could inject a spreadsheet expression into an exported lead record.
Attack Path
- An attacker creates or modifies a Google Maps business listing so that an exported field contains a spreadsheet formula, such as a value beginnin ...[truncated 1300 chars]
- Remediation
View remediation
Remediation Suggestions
Introduce a centralized sanitizer and apply it to every externally sourced value before both CSV and XLSX export.
- Treat values beginning with
=,+,-, or@as potentially dangerous. Also account for leading tabs, carriage returns, newlines, and whitespace that spreadsheet clients may ignore before formula detection. - Prefix dangerous textual values with a single quotation mark or otherwise encode them as literal text.
- For XLSX output, explicitly set externally sourced cells to text and apply a text number format. Do not rely exclusively on visual formatting to suppress formula evaluation.
- Preserve trusted, locally constructed hyperlinks only after validating their components. Validate
place_idbefore incorporating it into the generated Google Maps URL. - Apply the protection to all exported columns, not only the fields currently expected to contain free-form text.
- Add regression tests covering values such as
=1+1,+SUM(1,1),-1+2,@SUM(1,1), and formula prefixes preceded by tabs or carriage returns. - Document that generated spreadsheets contain externally sourced business data and should not be opened with legacy external-content or macro features enabled.
A sanitizer can follow this pattern:
python FORMULA_PREFIXES = ("=", "+", "-", "@") def spreadsheet_safe(value): if value is None: return "" text = str(value) probe = text.lstrip(" \t\r\n") if probe.startswith(FORMULA_PREFIXES): return "'" + text return textApply
spreadsheet_safeto every field passed tocsv.DictWriterand every externally sourced cell appended throughopenpyxl.- Treat values beginning with
