actual icon indicating copy to clipboard operation
actual copied to clipboard

[Bug]: SimpleFIN tokens are stored in plaintext

Open james4141 opened this issue 8 months ago • 9 comments

Verified issue does not already exist?

  • [x] I have searched and found no existing issue

What happened?

Opening issue per recommendation of youngcw from Discord

Because SimpleFIN (and presumably GoCardless) tokens are shared by all users of the server, they are stored in a plaintext .sqlite database which can be read by anyone who has access to the server. While not a major issue when self-hosted, it implies that operators of hosting services such as PikaPods have access to everyone's bank sync tokens. This gives them ability to access our SimpleFIN accounts and bank transactions, regardless of whether end-to-end encryption is enabled.

How can we reproduce the issue?

If self-hosting (docker), the db is located at: actual-server/server-files/account.sqlite This can be opened/viewed using a sqlite app to retrieve the SimpleFIN token stored in the secrets table. This is a live token and can be used to access your transactions. While not directly accessible to you when using a service such as PikaPods, the same structure/file likely exists and could be accessed by a person who owns/maintains those systems.

Where are you hosting Actual?

Docker (Unraid)

What browsers are you seeing the problem on?

N/A

Operating System

N/A

james4141 avatar Aug 13 '25 17:08 james4141

Yea, API keys are stored in a write-only state in the server (meaning: you cannot read them from the outside unless you have direct access to the server). Is there an alternative solution you are proposing here?

MatissJanis avatar Aug 21 '25 19:08 MatissJanis

Could the token be stored inside the budget file rather than be server-wide? That way it would be stored encrypted, and could potentially allow other users to have their own SimpleFIN accounts linked to their budget file.

james4141 avatar Sep 07 '25 18:09 james4141

Aren't budgets stored on local devices unencrypted? This could open up the amount of ways to compromise your tokens.

shall0pass avatar Sep 07 '25 19:09 shall0pass

That's a fair point. Though, I think I'd prefer the option of having the token stored unencrypted on my device rather than a server where someone else has access to it. Thoughts?

james4141 avatar Sep 08 '25 16:09 james4141

I thought encryption was required for bank sync, but after reading the docs, it's only "highly recommended". I'm a bit surprised by that.

Since this is a multi user problem, another approach could be create an encrypted file for each oidc user that contains this type of information. This could even restrict certain users from initiating a sync (only budget owners?). I'm not sure if that's desirable, but maybe possible?

shall0pass avatar Sep 09 '25 00:09 shall0pass

Because Bank Sync can only be run by the user via web interface, or API/helper scripts that authenticate as the user, your idea could work and maybe even be desirable. It's asked on Discord almost daily why multiple users on the same server need to share a SimpleFIN token - but I honestly don't know how much work would be required to allow per-user SimpleFIN tokens and store them within an E2E encrypted file.

Not to conflate two similar but separate issues - the main concern here was that individuals at PikaPods and other hosting services have access to our SimpleFIN tokens - even in in single-user setups with encryption enabled.

james4141 avatar Sep 09 '25 12:09 james4141

I've been going back and forth with this issue in my head.

From one perspective: yes, storing secrets in the server gives the server admin access to these secrets. This is applicable to Pikapods, AWS, Azure or any other cloud hosting provider. Technically they have access to secret keys or to just read the user database directly. But we trust these providers NOT to do that (and obviously there are laws and regulations around this as well). But if you are extra paranoid - there is no better spot to host Actual than on your own personal home server. An extra benefit to storing secrets on the server is - you set them up once and forget. You don't need to re-configure them each time you create a new budget file.

From another perspective: yes, we could move the secrets from the server database to the budget database (which is encrypted on the server and during transit, but un-encrypted on the local device). It would mean only you have access to the secrets and nobody else. But it would also mean - any malicious browser extension or computer virus could also access them without a problem.

Multi-user issue is something unrelated and should be fixed irrelevant of how the discussion goes here. Lets not mix the two things together.

In summary - I still think the existing solution is better than moving the secrets over to the client. If you don't trust the cloud provider - then by all means - don't use it. Host your own home server.

MatissJanis avatar Sep 16 '25 20:09 MatissJanis

I've been back and forth as well, and I agree especially with your last point - and appreciate having the option to self-host if this is of personal concern. I do think there's a certain level of risk when one bad actor could gain access to thousands (tens of thousands?) of user tokens - but the end of the day, even apps like YNAB have access to your transaction data, and if you're using SimpleFIN, then I'd assume that developer has at least some access, as well as the MX provider.

I guess the realization for me is what "end to end" encryption actually means in this case. I might suggest a few language changes to the in-app encryption notification and the website documentation. Statements such as "End-to-end encryption offers the ability for you to generate a key ... so that hosted services can't read the data" and "This guarantees that only you will ever have access to your data" aren't technically true, if you are using bank sync - while the budget file itself is E2E encrypted, the token to obtain the very same data is sitting there in plaintext.

james4141 avatar Sep 25 '25 15:09 james4141

Doc and in-app info updates makes sense to me! The e2e encryption is not applicable to bank sync or the bank sync tokens and it would be good to call that out. A PR for this would be more than welcome!

MatissJanis avatar Sep 27 '25 10:09 MatissJanis