Test files › Office documents › formula-injection.xlsx

Sample XLSX file (formula injection)

Workbook whose cells contain =, +, - and @ prefixed strings and a HYPERLINK formula.

↓ Download formula-injection.xlsx
Filenameformula-injection.xlsx
FormatXLSX
Size1.7 KB (1,733 bytes)
MIME typeapplication/vnd.openxmlformats-officedocument.spreadsheetml.sheet
SHA-256f3a7e7c4d1b67e339a5e918da7a81a3ac6bdb52f9581f63586774e1dcf8ed10b
What this file catchesThe XLSX cousin of CSV formula injection. When an app re-exports these cells to CSV, or a spreadsheet opens them, the payloads (all inert - a harmless calculation and a link) can execute. Confirm your export path escapes 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

Text cells starting with =, +, - or @ are harmless inside Excel, but become live formulas when your app exports them to CSV. Scan the sheet XML directly: an .xlsx is a ZIP, and cell text is either inline or in the shared-strings table.

import re
import zipfile
import xml.etree.ElementTree as ET

M = "{http://schemas.openxmlformats.org/spreadsheetml/2006/main}"
TRIGGERS = ("=", "+", "-", "@", "\t", "\r")

def text_of(el):
    return "".join(t.text or "" for t in el.iter(M + "t"))

found = 0
with zipfile.ZipFile("formula-injection.xlsx") as z:
    names = z.namelist()
    shared = []
    if "xl/sharedStrings.xml" in names:
        shared = [text_of(si) for si in ET.fromstring(z.read("xl/sharedStrings.xml")).iter(M + "si")]
    for sheet in sorted(n for n in names if re.fullmatch(r"xl/worksheets/sheet\d+\.xml", n)):
        for c in ET.fromstring(z.read(sheet)).iter(M + "c"):
            ref, kind, formula = c.get("r"), c.get("t"), c.find(M + "f")
            if formula is not None:
                print(f"{ref}: formula ={formula.text} (runs when the file is opened)")
                continue
            if kind == "s":
                text = shared[int(c.find(M + "v").text)]
            elif kind == "inlineStr":
                text = text_of(c)
            else:
                continue
            if text.startswith(TRIGGERS):
                print(f"{ref}: text {text!r} turns into a formula when exported to CSV")
                found += 1
print(f"{found} text cell{'s' * (found != 1)} to neutralise before a CSV export" if found else "no formula-like text")

Run against this file, it prints: B2: text '=1+1' turns into a formula when exported to CSV B3: text '+1+1' turns into a formula when exported to CSV B4: text '@SUM(1+1)' turns into a formula when exported to CSV B5: formula =HYPERLINK("https://example.test","click") (runs when the file is opened) 3 text cells to neutralise before a CSV export

Related guides and tools

Sample XLS and XLSX (Excel) filesFile signaturesMIME typesCheck a file's real typeVerify its SHA-256

Download & verify

curl -fsSL -o "formula-injection.xlsx" "https://files.hexaqa.com/office/formula-injection.xlsx"
curl -fsSL "https://files.hexaqa.com/office/formula-injection.xlsx" | sha256sum # expect: f3a7e7c4d1b67e339a5e918da7a81a3ac6bdb52f9581f63586774e1dcf8ed10b

More office documents test files

corrupt-missing-content-types.docxdocument.docxdocument.odtlegacy-workbook.xlsmacro-enabled.xlsmpresentation.odppresentation.pptxspreadsheet.ods

← All Office documents files