Skip to content

CSV export does not neutralise formula-injection characters in user-submitted cells #20

Description

@royalpinto007

Why it matters

app/api/export/route.ts builds the public CSV export. Its escapeCell() helper quotes cells that contain a comma, a double quote, or a newline, which is correct RFC 4180 escaping. But CSV files are usually opened in a spreadsheet, and a cell whose value begins with =, +, -, @, tab, or carriage return is interpreted by Excel, LibreOffice, and Google Sheets as a formula.

Case titles and outcomes in this export are user-submitted, so a submission titled =HYPERLINK("http://evil.example","click") ends up as a live formula in anyone's spreadsheet who downloads the export. This is the classic CSV injection issue.

What to change

In app/api/export/route.ts:

  1. In escapeCell(), prefix any value whose first character is one of = + - @ \t \r with a single quote (or another agreed neutraliser) before the existing quoting logic runs.
  2. Add \r to the set of characters that force quoting. A lone carriage return currently slips through.
  3. Add a test file app/api/export/route.test.ts covering escapeCell behaviour. The repo already has route tests to copy the shape from, for example app/api/posts/route.test.ts and app/api/admin/posts/route.test.ts.

escapeCell is module-private today, so exporting it for the test is fine and is the smallest change.

Notes

  • Run npm test and npm run format before opening the PR.

Questions are very welcome. Comment here to claim it and ask anything you are unsure about, you will usually get a reply within a day.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions