T09 · Insecure Skill Coding Practices
- Location
scripts/boss_cdp_raw.py:1293- Finding
Untrusted Job-Listing Fields Can Trigger Spreadsheet Formula Injection
- Content
View full analysis
Vulnerability Details
File Location:
scripts/boss_cdp_raw.py:607-634, 1293-1316
Vulnerability Type: CSV formula injection
Risk Level: MediumVulnerable Code
External job-listing fields are copied into the internal record without neutralizing spreadsheet formula prefixes:
python return { "title": raw.get("jobName") or "", "salary": raw.get("salaryDesc") or "", "salary_source": "api" if raw.get("salaryDesc") else "api_empty", "location": "\u00b7".join([ raw.get("cityName") or "", raw.get("areaDistrict") or "", raw.get("businessDistrict") or "", ]), "tags": " | ".join( t for t in (raw.get("jobExperience") or "", raw.get("jobDegree") or "") if t and t != "不限" ), "boss_name": raw.get("brandName") or "", "boss_title": raw.get("bossTitle") or "", "boss_active_status": map_list_boss_active_status(raw), "company_scale": raw.get("brandScaleName") or "", "company_stage": raw.get("brandStageName") or "", "company_industry": raw.get("brandIndustry") or "", "job_labels": " | ".join(raw.get("jobLabels") or []), "skills": " | ".join(raw.get("skills") or []),The values are subsequently written directly to CSV:
python def write_csv(csv_path, jobs): """将 jobs 列表写入 CSV 文件""" os.makedirs(os.path.dirname(csv_path) or ".", exist_ok=True) with open(csv_path, "w", encoding="utf-8-sig", newline="") as f: writer = csv.DictWriter(f, fieldnames=CSV_COLUMNS, extrasaction="ignore") writer.writeheader() for j in jobs: # 确保每列都有值 row = {col: j.get(col, "") for col in CSV_COLUMNS} writer.writerow(row) print(f"CSV 已保存: {csv_path}") def write_detail_csv(csv_path, details): """将岗位详情列表写入 CSV 文件""" os.makedirs(os.path.dirname(csv_path) or ".", exist_ok=True) with open(csv_path, "w", encoding="utf-8-sig", newline="") as f: writer = csv.DictWriter(f, fieldnames=DETAIL_CS ...[truncated 2656 chars]- Remediation
View remediation
Remediation Suggestions
- Introduce a centralized function that converts every externally sourced CSV value into a spreadsheet-safe literal before serialization.
- Treat cells whose first effective character is
=,+,-, or@as dangerous. Inspect after accounting for leading spaces, tabs, carriage returns, line feeds, and other control characters. - Prefix dangerous values with an apostrophe or use another export strategy that reliably forces literal-text interpretation in the supported spreadsheet applications.
- Apply the protection to every field in both
write_csv()andwrite_detail_csv(), rather than maintaining a partial field allowlist. - Preserve the original unsanitized values in JSON exports if exact source fidelity is required, while documenting that CSV exports are spreadsheet-safe representations.
- Add regression tests covering values such as
=WEBSERVICE(...),+1+1,-1+1,@SUM(...), and formula prefixes preceded by whitespace or control characters. - Document the mitigation and advise users not to disable spreadsheet protected-view or external-content warnings.
Example hardening pattern:
python FORMULA_PREFIXES = ("=", "+", "-", "@") def spreadsheet_safe(value): if value is None: return "" text = str(value) effective = text.lstrip(" \t\r\n") if effective.startswith(FORMULA_PREFIXES): return "'" + text return text row = { col: spreadsheet_safe(j.get(col, "")) for col in CSV_COLUMNS }The exact escaping convention should be tested against every spreadsheet application the project claims to support.
