Stop persisting raw Cashu proofs in localStorage#438
Open
ayushshrivastv wants to merge 2 commits into
Open
Conversation
|
@ayushshrivastv is attempting to deploy a commit to the shopstr-eng Team on Vercel. A member of the Team first needs to authorize it. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Metadata Leakage: When a user redeems a Cashu token, Shopstr merges the newly received Proof[ ]objects into the existing wallet state and writes the entire array directly into localStorage under the tokens key. These are not harmless balance records; elsewhere in the app the proofs are matched by proof.secret, confirming that the stored objects contain live bearer secrets.
Cashu proofs are effectively spendable ecash, so persisting them unencrypted in browser storage exposes wallet funds to any JavaScript running in the Shopstr origin. An XSS bug, compromised frontend dependency, or malicious extension can exfiltrate the stored proofs and redeem them elsewhere, resulting in direct theft of the user’s Cashu balance.
FILE:
components/utility-components/claim-button.tsx (line ~208)Before this PR, raw Cashu proofs were being written directly into browser localStorage under the tokens key from wallet, claim, checkout, and recovery flows. Since those proofs contain the spendable secrets themselves, that meant the wallet balance was being persisted as plaintext in browser storage.
After this PR, I changed that flow so Cashu proofs are kept only in runtime memory for the active session instead of being saved in localStorage. I also updated the existing wallet mutation paths to use one shared helper for token updates, added cleanup for any legacy persisted proof arrays on read, and added regression tests to make sure the wallet still works with the new storage behavior.