Cake Wallet Web Cannot Implement View-Only Wallets Securely: Browser Storage Vulnerabilities Explained
A user wants to monitor their Monero balance or Bitcoin holdings without exposing their spending keys to the internet. A view-only wallet solves this: it can display balances, verify incoming payments, and generate deposit addresses using only the public view key, leaving the private spend key offline and secure. The appeal is immediate. Monitor across devices, check payments from a phone or public computer, and never broadcast a secret capable of moving funds. But when this design moves to the web, the security model breaks entirely. Browser storage—whether LocalStorage, IndexedDB, or sessionStorage—cannot reliably protect cryptographic keys against an opponent with code execution, XSS vulnerabilities, or malicious scripts embedded in dependencies.
The problem is not that encryption in the browser is impossible. It is that encryption depends on where the key lives. A view-only wallet in a browser-based cryptocurrency application must store the view key somewhere the application can retrieve it on each session. That storage is accessible to any script running in the same origin, any extension with broad permissions, any compromised dependency, and—critically—any attacker who can inject JavaScript into the page. The distinction between a view-only wallet in a native application like Cake Wallet and a web-based one is not merely inconvenient. It is a fundamental architectural difference that determines whether privacy is preserved or undermined at scale.

Why browser storage cannot protect a view key
A view-only wallet requires the public view key to derive stealth addresses in Monero, monitor payment confirmations, and display historical transactions without ever touching the spend key. The Monero protocol, as documented in the Monero Project’s official specifications, relies on this separation: the view key permits scanning the blockchain for owned outputs, but cannot authorize spends. This is cryptographically sound when the view key is stored in a location the attacker cannot read. In a browser, no such location exists within the application’s control.
LocalStorage in a browser is a simple key-value store attached to an origin (scheme, domain, port). Any JavaScript code running in that origin can read LocalStorage values using a single line: localStorage.getItem('viewKey'). This includes your application code, malicious ads in third-party scripts, compromised npm dependencies, browser extensions with overpermissive manifests, and attackers exploiting XSS vulnerabilities in unrelated parts of the page. The browser does not distinguish between legitimate and malicious script; it executes all scripts in the same origin with the same access to LocalStorage, cookies, and the DOM.
Developers often respond to this by encrypting the stored value before writing it to LocalStorage. The view key is encrypted with a password, stored as ciphertext, and only decrypted when needed. This approach has a critical flaw: the decryption key must live somewhere. If it is derived from the user’s password using a key-derivation function, the password must be entered into the page on each session, introducing a phishing attack surface and requiring the user to type the password into a potentially compromised site. If the encryption key is derived from a local secret (a seed phrase or mnemonic), that secret must be imported or stored, returning to the original problem. If the application itself holds the encryption key in memory, an attacker with code execution—the assumption we are defending against—simply reads the key from memory after loading the page.
The encryption itself may be cryptographically correct. AES-256, for example, is a strong cipher. But encryption is only one component of security. The architecture must prevent the attacker from accessing the key, not just the ciphertext. In a browser environment, this is not possible for data that must be accessible to application code without re-authentication for each operation.
Attack surface: how a view key can leak from browser storage
Suppose a user visits a Cake Wallet web version and imports a Monero view-only wallet using the public view key. The application encrypts the key, stores it in LocalStorage, and displays balances. What can go wrong?
Scenario 1: Malicious dependency. The application includes a charting library, a utility function, or an analytics package from npm. One of those dependencies is compromised, or a developer publishes a trojanized update under a name similar to the real library. The malicious code runs in the page, enumerates LocalStorage, and exfiltrates all stored data to an attacker’s server. The encryption key, if it is held in memory or derived from a weak source, is also captured. Modern supply-chain attacks target exactly this surface.
Scenario 2: XSS vulnerability. The application has a reflected or stored XSS vulnerability in an input field, transaction display, or user-provided content area. An attacker crafts a URL or injects code that executes JavaScript in the victim’s browser. That code decrypts LocalStorage, reads the view key, and sends it to an external server. The legitimate code may be well-written; the vulnerability is in a third-party component or a subtle input-validation miss.
Scenario 3: Browser extension. A user installs a browser extension for password management, ad blocking, or crypto price tracking. The extension has overpermissive manifest permissions or is itself malicious. It reads data from the page’s LocalStorage, accesses the DOM, or intercepts network traffic. View keys and seed phrases stored in browser-accessible locations are extracted.
Scenario 4: Compromised CDN or man-in-the-middle attack. The JavaScript serving the Cake Wallet web application is hosted on a CDN. An attacker compromises the CDN, gains BGP control, or performs a man-in-the-middle attack on the connection. The served JavaScript is replaced with code that steals credentials and keys. Even if the legitimate application is well-designed, the attacker now controls what code runs in the user’s browser.
Each of these scenarios is not hypothetical. They have occurred against cryptocurrency wallets, exchanges, and mainstream web applications. The common thread is that browser-based storage and code execution are in the same trust domain. You cannot separate them without fundamentally changing the architecture.
Why a native application enforces better isolation
Cake Wallet is distributed as native applications for iOS, Android, macOS, and Linux. Each platform provides storage isolation mechanisms that a browser cannot offer. On iOS, the application’s sandbox is enforced by the operating system. Data stored in the app’s Documents directory is encrypted at rest using iOS’s Data Protection API, and access is controlled by the app’s entitlements. Other apps cannot read the directory. Malicious JavaScript cannot run in the iOS app because the app is compiled, signed, and verified before installation.
On Android, the sandboxing is less strict than iOS, but the principle remains: an application’s private data directory is protected by Unix file permissions. The application’s code is packaged in an APK, which can be signed and verified. If the application is sideloaded or installed from an untrusted source, security is compromised, but the vulnerability is known and requires deliberate action by the user.
On macOS and Linux, the application can use encrypted storage, privilege separation, and system-level key management. macOS offers Keychain, a system service that stores secrets securely; Linux distributions include similar tools such as GNOME Keyring or pass. These are not perfect, but they offer isolation that a browser application cannot achieve. The operating system enforces that only the owning application can access the stored key without additional authentication.
More importantly, native applications do not execute untrusted code by default. An iOS or Android app does not load and run JavaScript from the network. It is compiled and distributed as a binary. If the binary contains malicious code, it is present at distribution time, not injected during runtime. This is why cake wallet web is less suitable for view-only wallet access than the native mobile and desktop versions: the native client controls what code executes, while a web client depends on the network and browser to deliver safe code on every load.
The fallacy of “the user can choose not to import sensitive keys”
A common suggestion is that web-based wallets should simply warn users not to import view keys into a browser. “Use the web version only for read-only viewing,” the argument goes, or “generate your view key locally first.” These suggestions misunderstand the threat model and the user’s actual choices.
First, most users do not sharply distinguish between a web interface, a mobile app, and a desktop app. They see “Cake Wallet” and expect the same level of security across all versions. If they import a view key into a web version, they reasonably assume the application handles it securely. A warning label may be overlooked, especially if the application functions normally.
Second, the convenience advantage of a web version is strongest for exactly this use case: monitoring a wallet from any device without installing software. A user who is traveling or borrowing a computer wants to check their balance. If the web version cannot safely store a view key, it cannot fulfill this central use case without resorting to workarounds that are less secure than the intended design.
Third, even a view-only key leaked to an attacker is damaging. The attacker cannot spend the funds, but they can observe all incoming payments, derive all stealth addresses, estimate the wallet’s value, and link transactions across time and addresses. For Monero, the view key enables this level of surveillance. For Bitcoin wallets using extended public keys (xpub), an attacker can derive all addresses and monitor balances. The user has lost the privacy benefit of the view-only design without losing the loss of funds. That is not a minor risk.
What the Cake Wallet native application does differently
The native Cake Wallet applications for iOS and Android implement view-only wallets using platform-provided secure storage. The public view key is encrypted and stored in the device’s secure enclave or system keystore. On iOS, the Secure Enclave is a dedicated coprocessor that performs cryptographic operations and holds keys such that they cannot be read by the main processor. The application requests the enclave to perform operations (decrypt, sign, verify) but never retrieves the raw key into memory where it could be dumped or intercepted.
This does not mean native applications are unbreakable. A device that is physically compromised, jailbroken, or running modified firmware may allow an attacker to extract keys. A user who loses the device loses access to the keys stored on it. But the security model is clear: data is protected by the operating system’s enforcement, not by encryption layers that depend on the application to manage keys correctly.
View-only wallets in Cake Wallet also support hardware wallet integration via Ledger and Trezor. When connected to a hardware wallet, the view key remains on the device and is never imported into the phone or computer. The phone serves as a user interface that communicates with the hardware device over a signed channel. The Ledger or Trezor holds the actual keys and performs cryptographic operations without exposing them.
The open-source code of Cake Wallet is available on GitHub, where the repository contains implementation details and security audit information. Users who wish to verify the security properties can inspect the source code, compile it themselves, and be confident that they are running the code they reviewed.
Browser isolation technologies and their limits
Modern browsers have introduced isolation mechanisms such as Content Security Policy (CSP), Subresource Integrity (SRI), and iframe sandboxing. These are genuine improvements for reducing certain attack surfaces. CSP restricts where scripts can be loaded from, reducing the risk of injecting external malicious code. SRI ensures that a script’s hash matches a known value, preventing CDN tampering. Iframe sandboxing limits what code running in an iframe can access.
None of these technologies solve the fundamental problem: if an attacker can inject or execute code within your application’s origin, they can read LocalStorage, access the DOM, and exfiltrate data. CSP cannot prevent an attacker-controlled script running at your origin from reading data. SRI cannot prevent a malicious dependency with a matching hash from stealing keys. Sandboxing does not help if the attacker’s code is running in the main frame, not in an iframe.
Service Workers and web workers are sometimes proposed as isolation layers. A Service Worker can encrypt data before storing it and decrypt it only on explicit request. But the encryption key must be stored or derived somewhere accessible to the worker, and a Service Worker itself is code that can be modified or compromised. The isolation it provides is at the level of avoiding accidental data leaks, not defending against determined attackers with code execution.
The hardest isolation technology to deploy in a browser is the key derivation function. If a user’s password is used to derive the encryption key, the password must be entered into the page on every session. This introduces a phishing risk: an attacker can create a login screen that looks identical to the legitimate one, capture the password, and use it to decrypt stored keys. Monero users familiar with view-only wallet setup know that the view key is typically 64 hexadecimal characters—not something a user should type into a web form.
The path forward: accepting native application limits
The conclusion is not that web-based cryptocurrency applications are useless. They can display public information, facilitate trades through custodial services, and provide educational interfaces. But they cannot securely store private keys, view keys, or any cryptographic material that an attacker with code execution should not access. This is not a limitation of Cake Wallet specifically. It is a limitation of the web platform.
For users who need to monitor a view-only Monero, Bitcoin, or Litecoin wallet from multiple devices, the secure approach is to install the native Cake Wallet application on each device. The native applications are free and available for iOS, Android, macOS, and Linux. They provide hardware wallet support, integrated privacy tools including Bitcoin Silent Payments and PayJoin, and Litecoin MWEB integration. The view key is stored in the operating system’s secure storage, not in a browser’s LocalStorage.
Alternatively, users can store view keys only on air-gapped devices or in hardware wallets, then use web interfaces only for information lookup. Tools like a Ledger Nano S or a dedicated device running the Cake Wallet application can remain offline until needed for operations. This approach sacrifices convenience but eliminates the attack surface of importing secrets into a shared device.
The tradeoff is explicit: convenience versus security. A web interface is convenient because it requires no installation and works everywhere. But that convenience comes from the browser’s ability to run any code, any time, without isolation from other websites or scripts. If you need to store cryptographic secrets, you must sacrifice the convenience and use a native application or air-gapped device.
Verification and testing: what users can do now
If you have used a Cake Wallet web version or another web-based wallet to import a view key, consider your exposure. If the view key is for a Monero wallet, all your transaction history and approximate balance may be observable by an attacker who accessed the browser storage. If the view key is for a Bitcoin extended public key, all your addresses and balances are compromised. Moving the funds to a new wallet created natively on a fresh device is the safest course.
For new wallets, use the native Cake Wallet application. The application is installed directly from the app store or from the official GitHub repository, and the code is open-source and auditable. On first setup, create a new wallet or restore from a seed phrase. Never import a view key or seed phrase into a web browser.
If you are testing or comparing wallets, be clear about what code is executing and where secrets are stored. Check the application’s storage settings and understand whether data is held on your device or on a server. For view-only monitoring, prefer applications with demonstrated security track records, hardware wallet integration, and—importantly—native distribution.
The Tor Project provides guidance on secure communication and network privacy, which can inform your choice of how to access wallet applications. Native applications can route through Tor, while web applications depend on the browser’s Tor handling and the server’s configuration. This is another reason native applications are preferable for privacy-sensitive operations.
Frequently asked questions
Can I safely use Cake Wallet web for a view-only wallet?
No. Any web application, including cake wallet web, cannot securely store view keys or other cryptographic material in browser storage. Use the native Cake Wallet application for iOS, Android, macOS, or Linux instead. The native versions use the operating system’s secure storage and are free to download.
What if I already imported a view key into a browser?
Consider your view key compromised if the browser could have been accessed by malware, extensions, or XSS attacks. For Monero, this means your transaction history and approximate balance may be observable. For Bitcoin, your addresses and balances are exposed. Move funds to a wallet created natively on a secure device and treat the old wallet as publicly visible.
Can encryption or security tools make browser storage safe for view keys?
No. Encryption cannot solve this problem because the encryption key must be stored or derived somewhere accessible to the application code. If an attacker can run code in the browser, they can extract the encryption key, decrypt the view key, or intercept operations. The isolation must be architectural, not cryptographic. Use native applications or hardware wallets instead.


