Test files › Structured data › formula-injection.csv

CSV formula injection test file

Cells beginning with =, +, -, @ and tab, which spreadsheet applications interpret as formulas. The payloads are non-destructive: they reference HYPERLINK and a harmless calculation.

↓ Download formula-injection.csv
Filenameformula-injection.csv
FormatCSV
Size357 bytes (357 bytes)
MIME typetext/csv; charset=utf-8
SHA-256c591c3c65f09f7ce69b6b47558650baf9ad511d14df5c95e0fdd9977bcbf0d0f
What this file catchesCSV export endpoints that write user-supplied data unescaped. When a victim opens the export in Excel or Sheets, the formula executes in their context. Correct mitigation is prefixing risky cells with a single quote or wrapping them.

Handle it in code

Each snippet below was run against this exact file with Python 3.14.4 and Node 24.15.0 when this page was built, and the output shown is what it printed.

Python

Neutralise cells that a spreadsheet would run as a formula when you export user data to CSV. This is the OWASP recommendation: prefix a single quote.

import csv

def neutralise(cell):
    # Excel and Sheets treat a cell starting with any of these as a formula.
    return "'" + cell if cell[:1] in ("=", "+", "-", "@", "\t", "\r") else cell

with open("formula-injection.csv", newline="", encoding="utf-8") as src, \
        open("safe.csv", "w", newline="", encoding="utf-8") as out:
    writer = csv.writer(out)
    for row in csv.reader(src):
        writer.writerow([neutralise(c) for c in row])

with open("safe.csv", encoding="utf-8") as f:
    print(f.read().splitlines()[1])

Run against this file, it prints: '=1+1,Formula in name column,evaluates to 2 if unescaped

Node.js

The same rule in JavaScript, applied to each cell before you quote and join it.

const neutralise = (cell) => (/^[=+\-@\t\r]/.test(cell) ? "'" + cell : cell);

for (const cell of ['=1+1', '+1+1', '-1+1', '@SUM(1:10)', 'plain text']) {
  console.log(JSON.stringify(cell), '->', JSON.stringify(neutralise(cell)));
}

Run against this file, it prints: "=1+1" -> "'=1+1" "+1+1" -> "'+1+1" "-1+1" -> "'-1+1" "@SUM(1:10)" -> "'@SUM(1:10)" "plain text" -> "plain text"

Related guides and tools

Sample CSV fileCharacter encodingsUpload validation checklistVerify its SHA-256

Download & verify

curl -fsSL -o "formula-injection.csv" "https://files.hexaqa.com/csv/formula-injection.csv"
curl -fsSL "https://files.hexaqa.com/csv/formula-injection.csv" | sha256sum # expect: c591c3c65f09f7ce69b6b47558650baf9ad511d14df5c95e0fdd9977bcbf0d0f

More structured data test files

1000-rows.csv1million-rows.csvbom-and-semicolons.csvquoting-nightmare.csvragged-rows.csvvalid-simple.csvdeeply-nested-100000.jsonlarge-array-100mb.json

← All Structured data files