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| Filename | formula-injection.csv |
| Format | CSV |
| Size | 357 bytes (357 bytes) |
| MIME type | text/csv; charset=utf-8 |
| SHA-256 | c591c3c65f09f7ce69b6b47558650baf9ad511d14df5c95e0fdd9977bcbf0d0f |
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"