pull down to refresh

Somewhat related to this post last year.
I admire the vision for what Mutiny, Cashu wallets, and other PWA-focused devs are building, but I must admit I am concerned by the PWA-maximalism which I have seen espoused here and on Nostr.

Background

If you're not up to speed: PWAs are very popular in the BTC space right now because (correct me if i'm wrong) Apple and Google are frequently censoring bitcoin and especially lightning applications submitted to their respective mobile app stores. PWAs offer an end-run opportunity where users can "install" a PWA on their mobile phones without either party needing to jump the Apple/Google garden walls.

Thesis

PWAs are a poisoned well for bitcoin wallet devs parched of free (libre) distribution channels. We can drink from this well for a while, but not forever, and certainly not if we expect the bitcoin wallet userbase to grow.

Survey

Consider your favorite PWA wallet. Let me ask you a few questions to see whether this PWA wallet is right for you.
  1. Are you OK with your wallet phoning home to the developers every time you open it?
  2. Are you OK with wiping your seed every time you clear your browser cookies/storage?
  3. Are you OK with your wallet constantly loading and executing code served by a remote computer?
  4. Can you accept the risk that a single successful domain-name takeover or BGP hijacking attack on the PWA would result in your wallet seed being permanently and silently exposed? (IF you open your wallet at the time of the attack)
  5. Are you aware that TLS - a historically flawed and brittle encryption protocol - is the ONLY way a PWA wallet installation can be verified? (no PGP signatures)
  6. Can you accept that a TLS middle-man can compromise your wallet any time you open it on an insecure network?
  7. Do you trust the entire distribution pipeline of the wallet with your money? This includes the software used in building the wallet itself (which is fundamentally just a bunch of HTML/CSS/JS files), and also the services used to distribute those files, like AWS, Cloudlfare, DNS servers, certificate authorities, and all the web2 technology stacks they depend on.
  8. Do you trust your browser's developers to properly enforce site isolation? (e.g. if you open evil.com in a new tab, that site shouldn't be able to read or write to the memory/storage of the mutinywallet.com tab).
  9. Have you planned and tested how you will recover your money if the wallet's domain is taken offline tomorrow?
  10. Can you live with the risk of governments seizing or silently surveilling your wallet? (Think of how effectively the US government could have deanonymized or rug-pulled users of the now-seized Samourai wallet if it had been distributed as a PWA)
If you can answer "yes" to all the above questions, then keep calm and carry on: PWAs are a fine choice for you.
If not... perhaps you should take a deeper look.

App Stores Suck Too

I'm not saying apple and google's walled gardens are any better. They rely on similar flawed infrastructure to distribute apps to their users. However there are two very important distinctions to be emphasized:

1. PWAs cannot be signed, verified, or reproduced

2. PWAs are updated every time you open them

The combination of these two properties is what makes PWAs toxic, in my view at least.
By comparison, app stores distribute builds which are signed by the developers so that updates can be verified after initial installation without trusting the distribution pipeline. Auto-updates can be disabled if needed. For android apps installed directly by APK, one can even add a layer of PGP verification or manual APK-signature verification.
Bitcoin Core is probably the best example of safe software distribution: It is compiled with reproducible builds, PGP-signed by numerous developers, and intentionally shipped without any centralized auto-update or phone-home mechanism, because those could be used to force undesirable changes onto unwilling users.
Security-sensitive software in general should be updated only with the consent of the user, because the user relies on the software to act in their interest, as their agent and representative in the digital world. A software which changes itself arbitrarily can easily morph into something which acts against the user.
Obviously a PWA wallet for pocket spending money is not as high-value a target as the base-layer bitcoin node software, but that argument only works for as long as the sum value of money stored in that wallet across all users remains small. If any wallet gets popular enough, even with very small individual balances, the wallet software and distribution pipeline will eventually become a desirable target.

An Easier Target

Put yourself in the position of a hacker targeting self-custodial wallets. Since private keys live on users' devices, you'll only be able to steal bitcoin if you can sneak your malicious code into a wallet update, or otherwise compromise a user's device.
You have the the choice between two wallets: one distributed by app store, and one distributed by PWA, both otherwise identical in attack surface, protecting an equal value of bitcoin. Which do you attack?
You attack the PWA. Why?
  • Your malicious code stands more chance of reaching more victims faster, because updates are always automated and are fetched far more frequently. This means a bigger payout for your effort.
  • The distribution pipeline has more attack surface due to the lack of build-signing. This means the attack itself will be easier and cheaper to execute.

From Source

Most of the risks i've mentioned so far can be resolved if one builds and runs the PWA wallet from its source code.
Unfortunately PWAs are very difficult to build from source. Whereas a desktop or mobile app can be built from source with varying degrees of difficulty and then simply installed and executed, a PWA must be built, AND served over an HTTP connection to a browser, and so the user must also supply their own HTTP server and figure out how to set up TLS, reverse proxies, SSH tunnels, or other ways of routing their browser's HTTP request to the server running the PWA.
Often open source PWAs are not meant to be run from source by amateurs. Devs don't always document the build process or how to serve that build securely. And so most people can't figure it out, and just use the devs' own published PWA URL. We're back to square 1.

Conclusion

A PWA wallet is certainly better than no wallet at all. But I would urge devs who ship PWA wallets to also ship a binary distribution of their app which is securely signed, and does not auto-update itself.
Long term, i believe developer-driven distribution tools like F-Droid and Obtanium are the answer. I expect the EU will soon force apple to allow users to install apps manually on iOS devices, like Android users can currently do. PWA wallets will then no longer be necessary or desirable, and we can avoid learning our lesson the hard way.
You're half right, PWA's defeat the purpose in the context of a mobile node because it's implicitly trusted for a lot of those reasons mentioned.
You also left out my favorite part, in that a PWA can't even communicate to the Bitcoin or Lightning Networks by itself... so all the data is proxied too.
In that context, yes it is totally moronic why anyone would use that.
However, PWA's are just as valid of an access device as anything else wrt a remote node authenticating device tokens that can be scoped and revoked. Maybe that's why the wallet you mention seems to have left Bitcoin to focus on EDollars?
The level of supply chain paranoia you've applied to PWA's, if applied to native apps given general user practices, just moves the concerns around and doesn't obviate them. There's a usability tradeoff for every step removed from cloning the core git repo and building it yourself on a dark network within a faraday cage.
Also, I don't believe there are any storage focused PWA's that store keys in localstorage in a 1:1, the surface area of anything economic facing is implicitly a hot and transparently making those usability tradeoffs.
reply
The level of supply chain paranoia you've applied to PWA's, if applied to native apps given general user practices, just moves the concerns around and doesn't obviate them.
Even a naive user who blindly installs updates to an android app will still receive the assurances of signed and verifiable APKs, so that after first install the user can at least be certain their updates are shipped and approved by the same developer. PWAs have no such verifiability mechanisms (unless i'm mistaken as Tony has tersely suggested).
Unlike native apps, PWAs have no easy way to disable auto-update for those like me who are more paranoid. You'd need to block the PWA's domain on the OS or network level, and hope the PWA still works while it's offline.
You also left out my favorite part, in that a PWA can't even communicate to the Bitcoin or Lightning Networks by itself... so all the data is proxied too.
That's an excellent point. All the usual practical pitfalls of web-apps (performance, limited OS access) apply equally to PWAs, besides the pure security problems I pointed out. I'm coming at the problem more from the perspective of security/privacy than functionality.
reply
It's not that its not signed, its that its TLS signed as you say... but even a native app store is still using TLS for pretty much everything.
What superiority is there in a checksum or PGP key vs TLS if you're communicating that checksum or PGP key over TLS in the first place? If TLS is broken everything is (and I would agree that's plausible since I just assume the NSA always has the drop on everyone).
So, all things equal with TLS, it comes down to trusting the publisher in both scenarios too. I don't think there's a material percentage of people halting auto-updates that aren't just self-deploying, seems like a bit of a reach.
People do shit up their browsers with extensions and stuff that exposes their storage, maybe OS's are better at storage separation than browsers considering that... but extensions are just one form of social engineering attack a native app could iterate upon.
reply
What superiority is there in a checksum or PGP key vs TLS if you're communicating that checksum or PGP key over TLS in the first place?
It matters a lot because of who (or what) controls the signing key.
Consider bitcoin core. The devs who sign the bitcoin core releases each have a static PGP key which they publish on github. I download and store those PGP keys over TLS, so if my TLS connection is compromised at the time of my PGP key download, then I'm screwed.
But if my initial PGP key download is safe (or if the keys are PGP-signed by keys I already had and trust) then I can use them to verify any future download of bitcoin core, regardless of transport mechanism. I could download a signed bitcoin core from a torrent, or a plaintext FTP bucket, or a sketchy forum, and if the signatures on it are valid, then the download is authentic (assuming the signing devs are honest).
Note how the signing keys are controlled solely by the devs who built/reproduced bitcoin core, and so the signatures could only be made by them. I don't need to care about the provenance of the bitcoin core build i downloaded, as long as I trust the devs who signed off on that build to keep their signing keys safe.

Compare that with TLS.
A TLS server must possess two things: a certificate and a secret key. When a user's browser loads a PWA from a server, it checks that server's TLS certificate is signed by one of the known valid certificate authorities (CAs) stored in the user's browser, and confirms the server owns the public key listed in their certificate. It also checks the certificate is labeled with the correct domain. If these checks pass, then the connection can proceed.
All that TLS certificate really proves then is that the server has been authorized by a CA to control a given domain. It says nothing about the origin or authenticity of the data transmitted by that server. It doesn't even prove the user is talking to the same server today as they were yesterday, because certificates are intentionally set to expire and rotate regularly.
Note how the signing key with the real power here is controlled by the certificate authority. The server's key is just a secondary key whose bearer has been 'authorized' by the CA to act as steward of a given domain. There are so many attack vectors in this scheme it's difficult to even know where to begin, but the primary one is that the server can just serve malicious data.
That can't happen if you verify a build with a PGP key controlled personally by the developer.
reply
121 sats \ 1 reply \ @freetx 24 Jun
PWAs certainly have problems, however you are ignoring that you can "size your risk" quite effectively.
That is to say: Are PWAs a good solution for holding $10K? Obviously not. However is it an acceptable risk trade-off for $250....probably fine.
reply
I'm not ignoring that at all:
Obviously a PWA wallet for pocket spending money is not as high-value a target as the base-layer bitcoin node software, but that argument only works for as long as the sum value of money stored in that wallet across all users remains small. If any wallet gets popular enough, even with very small individual balances, the wallet software and distribution pipeline will eventually become a desirable target.
From the perspective of a user, yes, by all means store pocket change however you want if you feel the risk is acceptable. That's the same reasoning why I think ecash wallets in general have great potential.
Yet, in a perfect world with all else being equal, a rational user should always choose a native wallet software over a PWA wallet on the basis of security alone, perhaps with one or two rare exceptions like an untrusted-dev scenario.
That's why I would urge developers to ship their wallets as both native apps and PWAs. Let users decide for themselves how secure they want to be.
reply
A lot of your assumptions here are actually incorrect and you should spend more time researching PWAs before spreading FUD. I'm not going to waste my time disputing all these. Enjoy.
reply
106 sats \ 0 replies \ @Fabs 24 Jun
Psst, Tony, hè Tony, Tony! I'd be very keen on hearing what you have to say in regards to the above post in detail, please do!
reply
I would very much appreciate if you could elaborate?
reply
Would appreciate more elaboration here from Tony. i think we all have something to learn
FWIW i know that mutiny uses LDK rust with bindings compiled into wasm and deployed as pwa so thats actually alot of code running 'natively' on WASM. this includes alot of their security/wallet-signing code. (which is also i think why theres this setup phase at the start of the wallet - CMIIW) you're definitely not sending the seed up to the server to sign a message or running arbitrary signing code sent from the server
I'm not sure of all the guarantees but i think they are releasing the code open source and LDK is also open source so people can actually check?
i think some of the PWA critques here still stands but as always things arent extremely good or bad
reply
Naturally no sane wallet dev should be sending the seed to the server. But if the wallet's code, whether distributed as WASM, JS, PHP, or anything else is served over HTTPS, then the user's seed can also be compromised by the server if it simply serves the client malicious code.
Also, whether the code is open source or not has zero bearing on the code actually served to clients' browsers.
Yes PWAs are not good for security.
reply
I’m the solo developer of https://helm-wallet.com, a self-custodial PWA lightning wallet (that uses Liquid and Boltz under the hood) and I’ll make a comment on every point you made:
Are you OK with your wallet phoning home to the developers every time you open it?
This is not 100% true. https://helm-wallet.pages.dev is a static server, it only serves files. The code is open-source, you can check there’s no phoning home. Better than that, there’s no home to phone to.
I have no idea how many times the wallet is open or used. I believe it's not a bug, it's a feature.
Are you OK with wiping your seed every time you clear your browser cookies/storage?
True. In Helm, your seed is stored locally encrypted with AES256. If you lose your password or you clear your browser storage, you will in fact need to restore your seed. Having said that, with Helm you restore your seed in seconds.
Are you OK with your wallet constantly loading and executing code served by a remote computer?
You can run Helm locally, is easy as:
  • clone repo
  • yarn
  • yarn start
  • access app on your browser localhost:3000
Can you accept the risk that a single successful domain-name takeover or BGP hijacking attack on the PWA would result in your wallet seed being permanently and silently exposed? (IF you open your wallet at the time of the attack)
In order to minimize this risk, Helm can be run locally and is automatically deployed to more than one domain. I take advantage of webhooks to push code to 3 different repos (github, gitlab, bitbucket) and 2 automatic deploys (https://helm-wallet.pages.dev/ and https://bordalix.gitlab.io/helm-wallet/)
I'm looking for more free services like those, where I can automatically deploy a static site. A service like this based on Switzerland would be gold.
Are you aware that TLS - a historically flawed and brittle encryption protocol - is the ONLY way a PWA wallet installation can be verified? (no PGP signatures)
True. This is the facto trust level on the web industry. You rely on the same security when you access your home banking or any other sensible website. It’s not perfect, but it’s what we have.
Can you accept that a TLS middle-man can compromise your wallet any time you open it on an insecure network?
See previous comment.
Do you trust the entire distribution pipeline of the wallet with your money? This includes the software used in building the wallet itself (which is fundamentally just a bunch of HTML/CSS/JS files), and also the services used to distribute those files, like AWS, Cloudlfare, DNS servers, certificate authorities, and all the web2 technology stacks they depend on.
The key information here, your seed, is stored locally, encrypted with AES256, and available in plain text only on memory. It’s almost impossible for those in the distribution pipeline to do anything to steal it.
Do you trust your browser's developers to properly enforce site isolation? (e.g. if you open evil.com in a new tab, that site shouldn't be able to read or write to the memory/storage of the mutinywallet.com tab).
I tried :-) But don’t trust, verify.
Have you planned and tested how you will recover your money if the wallet's domain is taken offline tomorrow?
Good advice. With Helm users should restore their wallet and check for funds availability in different domains and locally. Everything should work just the same.
Can you live with the risk of governments seizing or silently surveilling your wallet? (Think of how effectively the US government could have deanonymized or rug-pulled users of the now-seized Samourai wallet if it had been distributed as a PWA)
Not entirely true: you can use PWA with Tor Browser and access only onion addresses. This feature is implemented on Helm wallet, exactly to minimize the risk you refer to. Using Tor, you hide your IP address from Boltz and from the chain explorers.
Just my 2 sats.
reply
Hi, and thanks for your work, helm looks cool! Clever choice to use Liquid swaps. I admire your choice to make it a static app, as those tend to work very well for running from source and can be deployed very easily.
Feedback: I just tried Helm out and unfortunately my money disappeared (0 balance shown) after depositing with LN. It reappeared once I refreshed the web page.
This is not 100% true. https://helm-wallet.pages.dev is a static server, it only serves files. The code is open-source, you can check there’s no phoning home. Better than that, there’s no home to phone to.
A static file server is still a server, and every time I open helm-wallet.pages.dev in my browser (and every time I open the PWA), my browser makes a GET request to helm-wallet.pages.dev to fetch an HTML file which dictates what UI to display and what code to execute. That's phoning home and auto-update at the same time. Maybe it's not your home, since pages.dev is controlled by cloudflare, but that's still phoning home, in my opinion at least.
Sounds like running the wallet from source would avoid this, so props to you for that choice! I love static sites in general.
The key information here, your seed, is stored locally, encrypted with AES256, and available in plain text only on memory. It’s almost impossible for those in the distribution pipeline to do anything to steal it.
It's absolutely possible. Simply distribute a version of the wallet's JS code which waits for the user to type her password in, and then decrypt the seed like the normal wallet does. Then the attacker can send the seed somewhere off-site or sweep the money to his own address.
Not entirely true: you can use PWA with Tor Browser and access only onion addresses. This feature is implemented on Helm wallet, exactly to minimize the risk you refer to. Using Tor, you hide your IP address from Boltz and from the chain explorers.
I'm not talking about IP addresses - i'm talking about deanonymizing on-chain transactions. If the gov had full access to individual samourai wallet seeds, they would have been able to see exactly who made which transactions and which TXOs belonged to whom, and so completely negate the purpose of coinjoining. And they could have confiscated that coinjoined money from anyone they wanted to at the same time.
I'm glad the justice department didn't attempt to distribute malicious samourai wallet builds after the seizure, because the same thing could've happened there to native apps. It's possible the only reason they didn't was because they didn't have the app-signing keys held by the samourai devs, and so the update wouldn't have been accepted by existing users' devices. This might have saved a lot of harm. A PWA would have been wide open to this class of malicious-update attack.
You can run Helm locally, is easy as:
Thank you! More wallet devs should make running from source easier. This is about the easiest you can make a static site to run so bonus points from me ++ :D
Pro tip: if you want to also distribute a native mobile application without changing your regular PWA build pipeline, you can create an app with Expo, bundle the static site files inside the application package, and then render the static site inside a WebView. For desktop, you can package and render the static site inside Electron (i'm guessing you probably have heard of that one before). Both approaches would help to avoid forced malicious update attacks, and would allow users to verify their installations automatically (app-signing) or out-of-band (with PGP).
reply
I will never make an iOS app, not while Apple has this on their Apple Developer Agreement.
I once made an Android app, for the sole reason (at the time) of having more accuracy on the user location. It's just a WebView for https://wheretosurftoday.com/, but now Google want's me to KYC :(
reply
In regards to the "phoning home" point, in web standards you can support offline mode, so it would be trust on first serve. However, as implemented Chrome force an update every 24 hours to prevent a website from being permanently hijacked. Trust is still required but not per request on sites that implement offline mode such as MutinyWallet.
reply
<3 <3
reply
Interesting read
reply
EU will soon force apple to allow users to install apps manually on iOS devices, like Android users can currently do. PWA wallets will then no longer be necessary or desirable, and we can avoid learning our lesson the hard way.
I don't think that's gonna happen in near future. Also, this move can't obsolete the demand of PWAs.
reply
stackers have outlawed this. turn on wild west mode in your /settings to see outlawed content.