[GH-ISSUE #5550] [Bug]: SimpleFIN tokens are stored in plaintext #9326

Closed
opened 2026-04-10 19:36:43 -05:00 by GiteaMirror · 10 comments
Owner

Originally created by @james4141 on GitHub (Aug 13, 2025).
Original GitHub issue: https://github.com/actualbudget/actual/issues/5550

Verified issue does not already exist?

  • 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

Originally created by @james4141 on GitHub (Aug 13, 2025). Original GitHub issue: https://github.com/actualbudget/actual/issues/5550 ### 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
GiteaMirror added the bank syncserver labels 2026-04-10 19:36:43 -05:00
Author
Owner

@MatissJanis commented on GitHub (Aug 21, 2025):

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?

<!-- gh-comment-id:3211900726 --> @MatissJanis commented on GitHub (Aug 21, 2025): 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?
Author
Owner

@james4141 commented on GitHub (Sep 7, 2025):

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.

<!-- gh-comment-id:3263969272 --> @james4141 commented on GitHub (Sep 7, 2025): 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.
Author
Owner

@shall0pass commented on GitHub (Sep 7, 2025):

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

<!-- gh-comment-id:3263976855 --> @shall0pass commented on GitHub (Sep 7, 2025): Aren't budgets stored on local devices unencrypted? This could open up the amount of ways to compromise your tokens.
Author
Owner

@james4141 commented on GitHub (Sep 8, 2025):

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?

<!-- gh-comment-id:3267167275 --> @james4141 commented on GitHub (Sep 8, 2025): 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?
Author
Owner

@shall0pass commented on GitHub (Sep 9, 2025):

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?

<!-- gh-comment-id:3268466990 --> @shall0pass commented on GitHub (Sep 9, 2025): 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?
Author
Owner

@james4141 commented on GitHub (Sep 9, 2025):

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.

<!-- gh-comment-id:3270619868 --> @james4141 commented on GitHub (Sep 9, 2025): 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.
Author
Owner

@MatissJanis commented on GitHub (Sep 16, 2025):

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.

<!-- gh-comment-id:3300236726 --> @MatissJanis commented on GitHub (Sep 16, 2025): 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.
Author
Owner

@james4141 commented on GitHub (Sep 25, 2025):

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.

<!-- gh-comment-id:3334776250 --> @james4141 commented on GitHub (Sep 25, 2025): 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.
Author
Owner

@MatissJanis commented on GitHub (Sep 27, 2025):

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!

<!-- gh-comment-id:3341486796 --> @MatissJanis commented on GitHub (Sep 27, 2025): 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!
Author
Owner

@hrv231 commented on GitHub (Dec 4, 2025):

The e2e encryption does not apply to bank sync or the bank sync tokens

I started using Bank Sync with SimpleFIN recently, and reading the docs made me believe that for security, it's best to use E2E.
Now that I know that the token is saved in plain text inside the account.sqlite file, for my case ( self-hosted ), I don't see the point in having E2E enabled.
I agree that the documentation needs to be updated.

<!-- gh-comment-id:3610400818 --> @hrv231 commented on GitHub (Dec 4, 2025): > The e2e encryption does not apply to bank sync or the bank sync tokens I started using Bank Sync with SimpleFIN recently, and reading the docs made me believe that for security, it's best to use E2E. Now that I know that the token is saved in plain text inside the account.sqlite file, for my case ( self-hosted ), I don't see the point in having E2E enabled. I agree that the documentation needs to be updated.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/actual#9326