CSV Injection: Why a Cell Starting with = Is Dangerous
CSV injection (formula injection) happens when a spreadsheet treats a cell beginning with `=`, `+`, `-` or `@` as a formula and runs it on open. Scraped data can carry a hostile cell like `=cmd|...`. Prefixing such cells with a single quote makes the spreadsheet show them as literal text.
Why it matters
A cell in a CSV file starting with =, +, -, or @ is treated as a formula by Excel, Google Sheets, and LibreOffice when the file is opened. An attacker can inject a hostile formula like =cmd|'/c powershell ...'!A1 to run arbitrary commands on your machine. Scraped web data can accidentally carry these patterns if a website publishes user input without sanitising it. Scalpel Tables escapes such cells by prefixing them with a single quote, rendering them as literal text.
How it works
When you open a CSV in Excel or Google Sheets, the spreadsheet parser scans each cell. If a cell starts with =, it is parsed as a formula. The formula can reference other cells (=A1+B1), call functions (=SUM(A:A)), or make external connections (=WEBSERVICE(...) in Excel, or execution via DDE). An attacker can craft a cell like:
=cmd|'/c calc.exe'!A1
Excel (or an older LibreOffice build) will attempt to execute the command.
The OWASP mitigation is simple: prefix such cells with a single quote '. When a cell begins with '=, the spreadsheet treats the entire content as text, not a formula. The ' does not display in the cell; it is a formatting marker. The cell shows as =cmd|... (the harmful-looking string) but it is inert text.
The same logic applies to +, - (negative-number sign; see below), and @ (DDE trigger in older Excel). Scalpel prefixes all four to be safe.
What does not matter
Negative numbers like -5 are a false alarm. Scalpel does not prefix a cell that is only a minus sign followed by digits. -5, -123.45 are formatted as numbers and remain harmless. Scalpel only prefixes -something, like -@SUM(A:A) (a rarer attack vector).
The prefix is an OWASP best practice for CSV export; it is not part of RFC 4180. Most modern tools treat quoted fields and inline-string cells safely. XLSX files (the Excel native format) do not need this prefix because they store cell types; a cell is either a number or text, and text cells are never formulas. Only CSV, TSV, and other text formats need the escaping.
The "Raw values" toggle lets you export without the prefix if you are sending data to a system that treats CSV as pure text and never opens it as formulas. But if a human opens the CSV in Excel, use the prefix.
Code example
Here is a hostile CSV cell and how Scalpel escapes it:
Raw (dangerous):
=cmd|'/c powershell -c "Start-Process calc.exe"'!A1
When opened in Excel on Windows, this attempts to start the calculator app.
Escaped (safe):
'=cmd|'/c powershell -c "Start-Process calc.exe"'!A1
When opened in Excel, the cell displays as text: =cmd|'/c powershell -c "Start-Process calc.exe"'!A1. No formula is run.
Another example, a cell starting with +:
Raw:
+2+3
Escaped:
'+2+3
In Excel, the raw version might be interpreted as a formula (+2+3 = 5). The escaped version displays as text (+2+3).
How Scalpel shows it
The "Escape formulas" toggle in the footer is on by default. When on, Scalpel scans every cell in every export (CSV, TSV, clipboard copy). If a cell starts with =, +, -, or @, it is prefixed with '. You can turn the toggle off if you are exporting to a trusted system that reads CSV as pure text, never as formulas. The setting applies only to text-based exports (CSV, TSV); XLSX files do not need escaping.