Skip to content

Formula injection in exports: guard XLSX as CSV, and test both (F3) #193

Closed

Description

@amar-python

Raised by the product owner on 4 Nov 2026 as "F3: spreadsheet formula injection" in the code review feedback. Not reproduced in this session. Repo #170 is a different "RV-F3".

The export path carries the risk: the "Invalid row export" feature downloads rejected rows as CSV, XLSX or PDF. A rejected row with a value such as =cmd would open as a formula in a spreadsheet.

What the code shows (verified at c7bebd1)

  • CSV: csv-table-hub-main/src/lib/export.ts guards with FORMULA_START = /^[=+\-@\t\r]/ in escapeCsv, which prefixes a quote. There is a test file, src/__tests__/export.test.ts. I have not confirmed it covers a =cmd value.
  • XLSX: the same file builds the workbook with XLSX.utils.json_to_sheet and applies no guard. SheetJS writes strings as text cells, so Excel should not evaluate them. That behaviour is not tested here.
  • Backend: no formula guard in api/ or build/csv/.

Decision (product owner, 4 Nov 2026)

Apply the same formula guard to XLSX as to CSV, for consistency.

Proposed

  • Add test cases to export.test.ts for =cmd, +cmd, -cmd, @cmd and tab-prefixed values, in both CSV and XLSX.
  • For XLSX, assert the cell is stored as text and that the guard prefixes the value.
  • Open the generated XLSX in a spreadsheet application to confirm the cell does not evaluate. Record which application and version.

Done when

  • The vitest run for export.test.ts shows the counts, with the new cases passing.
  • The new cases fail when the guard is removed (mutation check).
  • An XLSX sample and the spreadsheet application's result are attached to this issue.

Generated by Claude Code

Activity

  1. amar-python commented on Nov 9, 2026

    @amar-python
    OwnerAuthor

    Fixed in #202 (merged as 203c8ae).


    Generated by Claude Code

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

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions