T09 · Insecure Skill Coding Practices
- Location
scripts/auditor.py:466- Finding
CSV Formula Injection Through Untrusted File and Path Metadata
- Content
View full analysis
Vulnerability Details
File Location:
scripts/auditor.py, lines 466–484
Vulnerability Type: CSV formula injection
Risk Level: MediumThe CSV export function writes file names, paths, and comparison-report fields directly into CSV cells without neutralizing spreadsheet formula prefixes.
Vulnerable Code
python try: with open(output_path, 'w', newline='', encoding='utf-8-sig') as f: if data_type == "changes" and "changes" in data: writer = csv.DictWriter(f, fieldnames=["type", "file", "size", "size_before", "size_after", "diff_human", "ext"]) writer.writeheader() for row in data["changes"]: writer.writerow(row) print(f" 📄 对比报告已导出 CSV: {output_path} ({len(data['changes'])} 条)") elif data_type == "snapshot" and "files" in data: writer = csv.DictWriter(f, fieldnames=["path", "name", "size", "ext", "type", "modified", "hash"]) writer.writeheader() for row in data["files"]: writer.writerow(row) print(f" 📄 快照已导出 CSV: {output_path} ({len(data['files'])} 文件)") elif data_type == "validate" and "issues" in data: writer = csv.DictWriter(f, fieldnames=["type", "path"]) writer.writeheader() for row in data["issues"]: writer.writerow(row)Technical Analysis
File names and relative paths originate from the directory being audited. Comparison reports can also contain fields read from user-supplied or externally supplied snapshot JSON files. These values are passed directly to
csv.DictWriter.writerow().CSV quoting only preserves CSV syntax; it does not prevent spreadsheet applications from interpreting cells beginning with formula-triggering characters such as
=,+,-, or@. Some spreadsheet clients may also ignore leading whitespace or control characters before evalu ...[truncated 1885 chars]- Remediation
View remediation
Remediation Suggestions
Introduce a centralized CSV-cell sanitization function and apply it to every string field before passing rows to
csv.DictWriter.The sanitizer should:
- Detect values whose first meaningful character is
=,+,-, or@. - Account for leading whitespace, tabs, carriage returns, newlines, and other control characters that spreadsheet clients may ignore.
- Prefix dangerous values with an apostrophe or use another neutralization method verified against supported spreadsheet applications.
- Preserve unmodified values in JSON output when exact forensic fidelity is required, while treating CSV as a presentation format requiring sanitization.
- Sanitize all externally influenced fields, including
path,name,file,type,ext, and textual fields loaded from snapshot files.
Example hardening pattern:
python FORMULA_PREFIXES = ("=", "+", "-", "@") def sanitize_csv_cell(value): if not isinstance(value, str): return value candidate = value.lstrip(" \t\r\n") if candidate.startswith(FORMULA_PREFIXES): return "'" + value return value def sanitize_csv_row(row): return { key: sanitize_csv_cell(value) for key, value in row.items() }Each export loop should then use:
python for row in data["files"]: writer.writerow(sanitize_csv_row(row))Apply the same treatment to comparison changes and validation issues. Add regression tests using malicious file names and crafted snapshot fields beginning with each formula prefix, including variants preceded by whitespace or control characters.
- Detect values whose first meaningful character is
