Skip to content

[P2][Security] Add spreadsheet-safe handling for CSV exports #333

Description

@baixiangcpp

Summary

Several tools export user-controlled strings to .csv files using CSV quoting only. Quoting protects CSV structure, but it does not prevent spreadsheet applications from interpreting a cell beginning with a formula trigger as a formula.

A user who converts untrusted JSON/log data and opens the downloaded CSV in a spreadsheet can therefore execute spreadsheet formulas or external-link/DDE-style payloads supported by that application.

Affected paths

CSV/JSON Converter

escapeCSVField() quotes values containing quotes, delimiters, or newlines, but does not apply a spreadsheet-safety policy. JSON string values and generated headers can begin with =, +, -, @, tab, or carriage return.

UUID Generator

The user-controlled prefix/suffix are concatenated with generated UUIDs and exported to CSV. A prefix such as =1+1 produces a quoted cell that still begins with a formula marker.

Local Log Parser

Log messages are untrusted text and are always quoted in exportToCSV(), but a quoted message beginning with = or another formula trigger can still be interpreted by spreadsheet software.

Other CSV download paths should be audited and moved onto the same policy rather than each implementing escaping independently.

Why this matters

This is a local-first application, but local processing does not make an exported file safe to open. The relevant trust boundary is untrusted input -> generated CSV -> spreadsheet application.

Users reasonably expect a converter/export action not to create an active spreadsheet payload from inert JSON or log text.

Recommended implementation

Create a shared CSV export utility with two distinct responsibilities:

  1. RFC-compatible CSV structural escaping;
  2. an explicit spreadsheet-safety policy for string cells.

The safety layer should:

  • detect dangerous leading formula/control characters after the agreed whitespace policy;
  • neutralize them using a documented strategy compatible with target spreadsheet applications;
  • preserve genuinely numeric typed values such as negative numbers;
  • avoid double-neutralizing already-safe content;
  • apply consistently to headers and data cells;
  • optionally offer a clearly labeled raw/lossless CSV mode if exact string preservation is required, with a warning before download.

Do not rely on surrounding a value with double quotes as the formula-injection mitigation.

Acceptance criteria

  • Downloaded spreadsheet-safe CSV neutralizes string cells beginning with =, +, -, @, tab, or carriage return according to a documented policy.
  • Leading whitespace/control-character bypasses are covered.
  • Legitimate typed negative numbers remain numeric and are not corrupted by a blanket string prefix rule.
  • Headers receive the same protection as data cells.
  • CSV/JSON Converter, UUID Generator, and Local Log Parser use the shared exporter.
  • All other text/csv download paths are audited and either migrated or documented as non-user-controlled numeric output.
  • Tests demonstrate that CSV quoting alone is not treated as mitigation.
  • Round-trip behavior and any raw/lossless export option are documented in the UI.

Suggested regression fixtures

=1+1
+SUM(1,1)
-1+2
@SUM(1,1)
\t=1+1
\r=1+1

Also include safe controls such as numeric -42, ordinary text containing = later in the cell, commas, quotes, and multiline values.

Relevant files

  • src/features/tools/csv-json-converter/logic.ts
  • src/features/tools/csv-json-converter/page.tsx
  • src/features/tools/uuid-generator/page.tsx
  • src/features/tools/local-log-parser/utils.ts
  • src/features/tools/local-log-parser/page.tsx
  • shared CSV export helper/tests to be added

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions