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:
- RFC-compatible CSV structural escaping;
- 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
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
Summary
Several tools export user-controlled strings to
.csvfiles 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+1produces 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:
The safety layer should:
Do not rely on surrounding a value with double quotes as the formula-injection mitigation.
Acceptance criteria
=,+,-,@, tab, or carriage return according to a documented policy.text/csvdownload paths are audited and either migrated or documented as non-user-controlled numeric output.Suggested regression fixtures
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.tssrc/features/tools/csv-json-converter/page.tsxsrc/features/tools/uuid-generator/page.tsxsrc/features/tools/local-log-parser/utils.tssrc/features/tools/local-log-parser/page.tsx