T09 · Insecure Skill Coding Practices
- Location
scripts/archive_manager.py:50- Finding
Persistent CSV Formula Injection Through Untrusted Archive Fields
- Content
View full analysis
120 or any(char in code for char in "/\\\r\n,"): raise ValueError("Invalid parcel_code") provider = str(row.get("provider_name") or "").strip() if not provider: raise ValueError(f"{code}: provider_name is required") vertices = parse_boundary_coords(str(row.get("boundary_coords") or "")) errors = validate_coordinates(vertices, require_polygon=True) if errors: raise ValueError(f"{code}: {'; '.join(errors)}") validated = {header: row.get(header, "") for header in COUNTRY_HEADERS} validated.update( { "parcel_code": code, "provider_name": provider, "boundary_coords": build_boundary_string(vertices), } ) return validated ``` The resulting fields are passed to the generic CSV writer without spreadsheet-formula neutralization: ```python def write_csv(filepath, headers, rows): path = Path(filepath) path.parent.mkdir(parents=True, exist_ok=True) with path.open("w", encoding="utf-8", newline="") as handle: writer = csv.writer(handle) writer.writerow(headers) for row in rows: writer.writerow([row.get(header, "") for header in headers]) ``` ### Technical Analysis The archive validation checks that `provider_name` is non-empty but does not reject or neutralize spreadsheet formula prefixes. Other archive fields copied through the `validated` dictionary, particularly `provider_notes`, receive no formula-specific validation either. Python's `csv.writer` correctly quotes values for CSV syntax, but quoting does not prevent spreadsheet applications from interpreting cell c ...[truncated 2540 chars]- Remediation
View remediation
=HYPERLINK(...) =HYPERLINK(...) ``` 7. Verify the resulting files in all spreadsheet applications supported by the project, because formula interpretation and single-quote handling can vary between products. ]]>
