Safeguard
Application Security•

CWE-1236 CSV Injection: Formula Elements in CSV Files, and Fixes

User text exported to CSV can run as a spreadsheet formula when someone opens the file. Here is how it happens and how to neutralize it.

Safeguard Security Team
4 min read

CWE-1236 covers products that save user-provided information into a Comma-Separated Value (CSV) file without neutralizing, or while incorrectly neutralizing, special elements that a spreadsheet product may interpret as a command when it opens the file. It is often called CSV injection or formula injection.

Any application with an export button is exposed: admin panels, CRMs, reporting tools, contact forms that feed a spreadsheet.

How it happens

The attack starts when an attacker puts a formula into a field that your system stores, such as a name or a message. Later an employee exports the data and opens the CSV in a spreadsheet. A cell that begins with a formula character is treated as a formula and not as text.

MITRE's example is the hyperlink formula. A cell that begins with = can run =HYPERLINK(link_location, [friendly_name]). Stripping the leading equals sign, or not executing formulas from untrusted sources, impedes the attack.

The record lists three real cases:

  • CVE-2019-12134: a low privileged user could trigger CSV injection through a contact form field value.
  • CVE-2019-4521: a cloud management product allowed arbitrary command execution via CSV injection.
  • CVE-2019-17661: CSV injection in a content management system through formula code in a first or last name.

Notice who the attacker is. A low privileged user or an anonymous visitor writes the value, and a privileged employee triggers it later.

Vulnerable export code simply writes values as given:

import csv

def export(rows, path):
    with open(path, "w", newline="") as f:
        w = csv.writer(f)
        for name, email in rows:
            w.writerow([name, email])   # a name of =HYPERLINK(...) goes through untouched

A safer version neutralizes risky leading characters:

RISKY = ("=", "+", "-", "@")

def safe_cell(value):
    s = str(value)
    if s.startswith(RISKY):
        return "'" + s       # leading apostrophe makes Excel treat it as text
    return s

def export(rows, path):
    with open(path, "w", newline="") as f:
        w = csv.writer(f)
        for name, email in rows:
            w.writerow([safe_cell(name), safe_cell(email)])

What an attacker gains

MITRE rates the likelihood low. Attackers can populate fields that, once saved to CSV, attempt information exfiltration or other malicious activity when the spreadsheet software executes them automatically. The record lists reading application data and executing unauthorized code or commands. It also notes that current versions of Excel warn users of untrusted content, which is a mitigating factor but depends on the user reading the warning.

How to find it

MITRE lists automated static analysis (SAST) with high effectiveness. It traces data from sources of input to sinks, and a CSV writer is a sink that user data should not reach unneutralized.

Manual checks:

  • Find every code path that writes CSV, TSV or spreadsheet exports.
  • Enter =1+1 as your name in a form, export the data, and open the file. If the cell shows 2, the export is vulnerable.
  • Check imports too, since a file from one tool is often opened in another.

How to fix it

MITRE gives three mitigations, and is candid that none is perfect because spreadsheet products behave differently.

  1. Escape or remove formula sensitive characters from all data before storing it in the CSV. The risky characters are =, +, - and @. Effectiveness is moderate.
  2. If a field starts with a formula character, prepend a single apostrophe, which prevents Excel from executing the formula. Effectiveness is moderate, and MITRE says it is not clear how well it works in other spreadsheet software.
  3. Rely on spreadsheet settings that refuse to run formulas in untrusted files. Effectiveness is limited, because it depends on end users opening spreadsheets safely.

Combine the first two in code and treat the third as a bonus. Also tell staff who handle exports to open them in protected view when they come from user supplied data.

Try it yourself

Run a code scan against a sample project and see how user input reaching an export sink is flagged.

Click through it at your own pace, or open it full screen.

Quick check

Which characters start a formula in a spreadsheet?

MITRE lists the equals sign, plus, minus and at sign as the risky characters.

Does the apostrophe prefix fully solve it?

No. MITRE rates it moderate and says its effect in spreadsheet software other than Excel is not clear.

Who usually triggers CSV injection?

A person who opens the exported file, often an employee, after a low privileged user or visitor planted the formula in a field.

Sources

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.