Recognise the boundary
A customer name, delivery note or product comment is data when it sits in a database. The same text becomes a different risk when a staff member downloads it as a CSV file and opens that file in a spreadsheet. OWASP calls the problem CSV or formula injection: some spreadsheet applications interpret cells beginning with a formula marker as instructions. A retailer does not need to offer a spreadsheet editor for this to matter. A routine export for fulfilment, refunds or customer service can carry text that another person entered. The decision is therefore about the path from untrusted field to staff workstation, not just the download button.
Start by listing every field that can be changed by a customer, supplier, marketplace feed or public enquiry. Include names and addresses, but also reference numbers, free-text instructions and values copied from another system. Then list who receives each export and which application opens it. A report meant only for a program importer has different needs from a report a person sorts in Excel. The owner of the export should be able to say which purpose applies. Otherwise a protective prefix that makes the visible sheet safer may quietly alter the data used by the next system.
A quick visual scan of current customer records is not an adequate acceptance test. An attacker can choose future input, and harmless looking quoted text may be split into another cell by a weak CSV writer. OWASP warns about equals, plus, minus, at signs, control characters and some full-width variants. It also warns that separators and quotes can move a dangerous character to the start of a newly parsed cell. The correct unit of review is the final parsed cell after export, opening, saving and reopening, not the first character of the raw database value.
Choose an export for its real use
Separate a human-viewing export from a machine-readable data feed. For a staff spreadsheet, the primary goal is that untrusted values remain literal text when opened in the supported application. For an integration feed, the primary goal is faithful bytes and a documented schema. Trying to make a single CSV serve both goals without naming the trade-off creates hidden errors: a tab or apostrophe used to stop formula interpretation can become part of a customer name, account code or matching key. Provide distinct options or an explicit import contract when the two audiences both matter.
Correct CSV structure is a necessary first layer, not a complete security answer. The export writer should handle delimiters, quotation marks and line breaks as one field according to the chosen CSV dialect. OWASP ASVS specifically calls for RFC 4180 escaping and for protection against formula-leading characters. A second layer must consider what the target spreadsheet does with the resulting cell. OWASP notes that commonly suggested quoting and apostrophe techniques may fail after Microsoft Excel saves and reopens a CSV. It describes a tab prefix inside a quoted field for Excel-facing human reports, while also saying this is not universal across spreadsheet products or downstream importers.
Do not solve this by rejecting every unusual customer name or silently deleting punctuation. A legitimate reference may start with a plus sign, and addresses can contain commas or line breaks. Store the submitted value as business data under the normal validation rules, then apply output handling suited to the destination. Keep an internal, access-controlled record of the original value if the exported display needs a prefix. If staff edit and later reimport the report, document how prefixes are removed and how the import refuses unexpected formulas. That two-way path is a separate workflow and deserves its own test.
Rehearse an ordinary report
Imagine a small shop exporting paid orders for a morning dispatch run. One customer enters a delivery instruction that begins with an equals sign, another supplies a reference containing a comma and a quote, and a third enters a name beginning with a full-width plus sign. These are test records, not real incidents. The warehouse operator needs readable instructions, while the courier import requires unchanged order IDs. Produce the staff report and the courier feed separately. Confirm that each record still occupies one logical row, that the risky values appear as text in the staff application, and that the courier feed has exactly the agreed values.
The test should follow the actual staff journey. Download using an account with ordinary permissions, open the file in the supported desktop spreadsheet, save it, close it and reopen it. Inspect the parsed cells and any security prompts rather than assuming a prompt always appears. Repeat with the spreadsheet application and import path the team really uses; behavior may differ. Record the version tested and the export template version. A developer unit test that only compares raw CSV bytes is useful for quoting but cannot by itself show how a spreadsheet will interpret those bytes.
Include cases where a dangerous marker follows a quote, separator or line break within a submitted value. Also include ordinary punctuation, non-Latin names, long notes and empty cells so a fix does not make the report unusable. Check that staff can still identify the right order and that a machine feed can round-trip values without an unexplained tab. If a particular application cannot meet both interpretation and fidelity requirements, state that limitation at the export control. It is better to choose a narrower supported workflow than to advertise a universally safe CSV that nobody has verified.
Make the decision maintainable
Assign ownership of each export to a business user and a technical owner. The business user decides whether the file is for viewing, editing or system transfer, and identifies columns that must remain exact. The technical owner documents the serializer and the destination-specific handling, then tests the final file. Restrict access to customer data and choose a retention period through the organisation's normal privacy process; formula safety does not replace those controls. If a new column is added, the owner should decide whether it is untrusted before it enters the template.
A useful acceptance note is specific: name the export, the recipient, the spreadsheet version, the risky test values, the save-and-reopen result and any downstream import effect. If staff encounter a prompt or an unexpected formula, stop using that export for the affected workflow, preserve the test file securely and ask the owner to investigate. Avoid telling staff merely to click through warnings because the file came from an internal system; internal exports can contain external data. Review the decision when the spreadsheet product, CSV library or import contract changes.
The first practical step is to take one widely used export and trace it from one customer-editable field to the actual spreadsheet and any later import. This produces a concrete decision: keep a separate machine feed, apply the tested staff-view treatment, or replace an ambiguous export with a clearer format. It also gives a small business a finite acceptance test instead of a vague promise that all spreadsheets are safe. The evidence in OWASP and RFC 4180 supports the need for correct CSV structure and destination testing; the exact treatment still has to be verified in the applications your staff use.
Record an acceptance decision
A passing result should describe the environment, not just say “sanitised”. Name the export route, the customer-controlled columns, the CSV dialect, the viewing application and its version, and the import destinations. For each deliberately awkward test value, record the original stored text, the final parsed cell, the visible display after reopening and whether an import receives identical data. If the viewing file deliberately changes a value to keep it literal, put that difference in the export specification. This lets the next person understand why two files with similar columns are intentionally different, and it prevents an innocent cleanup from removing the protection.
Treat failure as a workflow defect with a clear owner. If a test cell is interpreted as a formula, disable that export path for routine staff use until the specific application path is corrected and retested. If a machine feed gains a hidden prefix, fix the separation rather than asking recipients to clean every row manually. Where multiple departments use the same file, confirm each use before changing its format; the warehouse may sort it visually while accounting may import it automatically. The decision is complete only when both groups can explain which file they should use, what each field means and how to report an unexpected cell.
If your team has no agreed spreadsheet application, make that decision before approving a control. A file tested in one desktop product may be opened later in a web viewer or passed to an accounting import. Name the supported destination on the download page, explain whether the file is for human reading or data exchange, and keep a sample with known awkward values for each route. This turns a security rule into a repeatable operational choice.
Checks before release
- Is every customer-editable column identified?
- Has the report been opened, saved and reopened in the supported application?
- Are human and machine exports separated where fidelity differs?


