* A native app can be installed once. A browser app is effectively downloaded fresh each time you use it. That give more exposure to attack. * A native app is downloaded, then run. A browser app does both in one step. Separation gives the user a chance to verify using hashes, signatures, etc, ideally cross checked from multiple different domains incase only the download server/primary domain is hacked. If there are sensitive user cookies, malicious javascript can steal them immediately on page load.
Native apps that update themselves can be a mess, but OS or package manager updates are generally carefully managed (I.E. apt).
For the CDN concern, sub resource integrity should work well (of course you need to verify that the version you hash is actually safe, which people sometimes skip). I think browser support is good these days.
But I agree, not intractable.
To reduce that risk, and temptation, we want to be in a model where the likelihood of detecting a compromised payload is increased. This is why software distributions like Debian are important, because they serve the same content to all their users, and there is a chain of verification that is established. One vigilant user is enough to detect that breach.
An even better solution is if the source code is available because it makes it easier for vigilant users to find those undesirable changes. This, paired with reproducible builds also allow to independently verify that the compiled output is indeed produced from that given source code.
Somewhere on that line we also have App stores which don't gives much more guarantees than the website but transfer that trust from the publishers to the application distribution platform. A compromised user still has the opportunity to capture the binary and submit it for analysis.
> In any E2E context you have to trust the client code.
I don't have to trust code which is continuously being delievered from the server. This is an intractable problem.
To add on to that, when there's an update, you usually can't diff it properly because large parts of the transpiled Javascript may change because of a one line change in the actual source code.
This is all assuming the website isn't actively trying to make it difficult for you to analyze their code.
At least if it's open source, you can inspect the source code then verify that the output is the same.
You have to trust it not to exfiltrate your local plaintext data, sure; but encryption and key management in a native app might be outsourced to a TPM chip, in a way where the native app can't steal the keys, nor decrypt anything "behind your back", in practical terms meaning there's a smaller surface-area of code to audit.
For native apps, you can install a particular version from source and not change it.
Sure, there are a couple extra steps needed here:
- The website author needs to avoid casually throwing in dependencies (unlike perhaps the average JS project)
- HTTPS for loading code resources is crucial; maybe even CDNs need to be avoided
- The user needs to avoid having browser extensions enabled
But the fundamental problem doesn't seem different nor intractable.