CVE-2026-46672 Overview
CVE-2026-46672 is a CSV formula injection vulnerability in @actual-app/cli, the command-line interface for Actual, a local-first personal finance application. Versions prior to 26.6.0 ship a hand-rolled CSV serializer in packages/cli/src/output.ts that fails to neutralize formula-injection prefixes when exporting data through the --format csv option. Any CLI command that streams user-controlled strings, including transactions list, accounts list, payees list, categories list, tags list, category-groups list, rules list, schedules list, and query, can emit cells that auto-evaluate when opened in Excel, LibreOffice Calc, or Google Sheets. The issue is fixed in version 26.6.0.
Critical Impact
Attackers can inject spreadsheet formulas into exported CSV files, leading to data exfiltration and arbitrary formula execution when a victim opens the file in a spreadsheet application.
Affected Products
- @actual-app/cli versions prior to 26.6.0
- Actual Budget application CSV export functionality
- Downstream tooling that consumes CSV output from the Actual CLI
Discovery Timeline
- 2026-07-07 - CVE-2026-46672 published to NVD
- 2026-07-08 - Last updated in NVD database
Technical Details for CVE-2026-46672
Vulnerability Analysis
The vulnerability is a CSV formula injection flaw classified under [CWE-1236]. The escapeCsv helper in packages/cli/src/output.ts implements RFC 4180 quoting rules for delimiters, quotes, and newlines. It does not, however, strip or escape leading characters that spreadsheet applications interpret as formula triggers, such as =, +, -, @, tab, and carriage return.
When an attacker controls transaction notes, payee names, category labels, or similar string fields inside an Actual dataset, exported cells retain the raw prefix. Opening the resulting CSV in Microsoft Excel, LibreOffice Calc, or Google Sheets causes the affected cells to be evaluated as formulas rather than displayed as text.
Successful exploitation depends on user interaction — the victim must open the CSV — and yields limited confidentiality and integrity impact within the spreadsheet context. Formulas can trigger network callbacks (via WEBSERVICE, IMPORTXML, or hyperlink evaluation), exfiltrate adjacent cell data, or attempt command execution through DDE payloads in older Excel configurations.
Root Cause
The CLI performed value stringification with formatCellValue(k, v) followed by escapeCsv, but the escape function only quoted values containing structural CSV characters. Strings such as =cmd|'/c calc'!A1 or @SUM(A1:A10) passed through unchanged because they contained no delimiter, quote, or newline. The exportToCSV helper in packages/loot-core/src/server/transactions/export/export-to-csv.ts shared the same gap.
Attack Vector
An attacker with the ability to write string fields into an Actual budget file, for example through a shared budget, imported bank data, or a malicious payee name, plants a formula payload. A downstream user later runs a CLI export such as actual transactions list --format csv > out.csv and opens the file in a spreadsheet application, at which point the payload executes.
// Patch in packages/cli/src/output.ts
if (data && typeof data === 'object') {
const entries = Object.entries(data);
const header = entries.map(([k]) => escapeCsv(k)).join(',');
- const values = entries
- .map(([k, v]) => escapeCsv(formatCellValue(k, v)))
- .join(',');
+ const values = entries.map(([k, v]) => formatCsvCell(k, v)).join(',');
return header + '\n' + values;
}
return String(data);
// Source: https://github.com/actualbudget/actual/commit/068185751c03b42e726e3c60b718413d5f96c306
// Patch in packages/loot-core/src/server/transactions/export/export-to-csv.ts
import { aqlQuery } from '#server/aql';
import { integerToAmount } from '#shared/util';
const FORMULA_TRIGGERS = /^[=+\-@\t\r]/;
const csvStringifyOptions = {
header: true,
cast: {
string: (value: string) =>
FORMULA_TRIGGERS.test(value) ? "'" + value : value,
},
};
// Source: https://github.com/actualbudget/actual/commit/068185751c03b42e726e3c60b718413d5f96c306
The fix prefixes any string starting with a formula trigger character with a single quote, forcing spreadsheet applications to treat the cell as literal text.
Detection Methods for CVE-2026-46672
Indicators of Compromise
- CSV files generated by @actual-app/cli versions below 26.6.0 that contain cells beginning with =, +, -, @, \t, or \r
- Actual budget records with payee, note, category, tag, or rule fields whose string values start with formula trigger characters
- Spreadsheet processes spawning child processes such as cmd.exe, powershell.exe, or bash immediately after opening an exported CSV
- Outbound HTTP requests from Excel or LibreOffice hosts to unfamiliar domains shortly after CSV file open events
Detection Strategies
- Static-scan exported CSV files for cell values matching the regex ^[=+\-@\t\r] before distribution or ingestion
- Alert on installations of @actual-app/cli with a package version less than 26.6.0 across developer and analyst endpoints
- Correlate spreadsheet application launches with subsequent script interpreter or network utility execution using endpoint telemetry
Monitoring Recommendations
- Log CLI invocations that include --format csv and archive the resulting output for review
- Monitor DNS and proxy logs for lookups originating from Office or spreadsheet processes to non-corporate destinations
- Track file writes to shared locations by CLI processes and validate CSV content against a formula-injection linter
How to Mitigate CVE-2026-46672
Immediate Actions Required
- Upgrade @actual-app/cli to version 26.6.0 or later on every host that runs Actual CSV exports
- Review recently generated CSV exports for cells starting with formula trigger characters and quarantine suspect files
- Audit Actual budget datasets for user-controlled fields containing =, +, -, or @ prefixes and normalize them
Patch Information
The fix is available in Actual release v26.6.0, delivered via pull request #7859 and commit 0681857. Full technical context is published in GHSA-7gh7-258j-4mpq. The patch introduces a FORMULA_TRIGGERS regex and prefixes matching values with a single quote so spreadsheet software renders them as text.
Workarounds
- Post-process CSV output with a sanitizer that prepends a single quote to any cell starting with =, +, -, @, tab, or carriage return
- Import CSV files into spreadsheets using the text import wizard and set all columns to text format rather than double-clicking the file
- Disable automatic formula evaluation and DDE in spreadsheet applications where supported, or open exported files in a plain text editor for review
# Upgrade Actual CLI to the patched release
npm install -g @actual-app/cli@26.6.0
# Verify installed version
actual --version
# Sanitize an existing export as a stopgap
sed -E "s/(^|,)([=+\\-@\\t\\r])/\\1'\\2/g" out.csv > out.sanitized.csv
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

