> If you're going to use Electron, you HAVE to make sure it is updated with each update of Chromium.
I never really thought about this, but in retrospect, this is so blindingly obvious, and is almost certainly a potential exploit vector to a wide range of electron-based apps.
The big problem with Electron isn't that it forces you to keep up with Chrome, although that's important too, but rather that it links Node.js with content-controlled Javascript, so that DOM corruption vulnerabilities can be leveraged for RCE, even in the absence of a Chrome vulnerability. Most Electron RCEs that you've read about had nothing to do with Chromium.
There's a whole process for evaluating and auditing Electron applications, which is harder to do than auditing (for instance) a native mobile application or, probably, even a native desktop application.
> rather that it links Node.js with content-controlled Javascript, so that DOM corruption vulnerabilities can be leveraged for RCE, even in the absence of a Chrome vulnerability
Can you explain this further? How is it different than a web-app with a NodeJS backend?
Imagine you’re writing Javascript code on a webpage. You write `const fs = require(‘fs’)`. It throws an error because the browser has no idea what “require” or “fs” are.
In electron, you can configure your page to be interlinked with node, so that you could write `const fs = require(‘fs’)` and import the Node filesystem module. This is a big feature of Electron, but it also opens you up to a whole host of vulnerabilities.
For instance, you are never supposed to spin up a WebView like this and then just load random URLs (this is emphasized in the docs when they’re explaining how to do this). However, if you did, untrusted code on a random webpage would have access to the user’s filesystem.
> Under no circumstances should you load and execute remote code with Node.js integration enabled. Instead, use only local files (packaged together with your application) to execute Node.js code. To display remote content, use the <webview> tag or BrowserView, make sure to disable the nodeIntegration and enable contextIsolation
In electron the UI javascript is running in a separate process than the node javascript. They can communicate through Electron's IPC channel.
I wouldn't be too surprised if it could be exploited, but it's not as easy as require('fs'). Instead you have to send messages through the pipe and you'd have to know how to exploit the handlers at the other end in the NodeJs process.
I was on a phone before and didn't have the docs pulled up, but the thing I was referring to is called nodeIntegration (it's a boolean you set in the webPreferences object in the options object you pass to the BrowserWindow constructor).
Why would they need a node process? Are there things an Electron app needs to do that isn’t possible from the Chrome runtime? And more importantly, why would they need to directly link with the DOM?
Well, one very simple example is access to filesystem. You can't do that from Chrome but can from node. In this particular case for example WhatsApp could have a cache of the images and videos attached to a conversation, without having to obey the limits of local databases imposed by PWAs.
The way I author my Electron apps to avoid this is to have a HTTP/Websocket server spin up at a random port, and then use that process to open an Electron window, with Node integration disabled.
This then becomes exactly the same as writing a web app, with anything that cannot be done by the renderer (Ex: file access) being done by the 'server'. Always wondered why this was not an officially strictly recommended way of doing this.
Correct me if I misread. You're leaving ports open on a customer machine, which has its own potential for security issues, even if you bind to localhost.
Wasn't there a Mac app that recently got a lot of flack for this?
Yes that's correct. And AFAIK the consequence was that any browser tab capable of running javascript could make HTTP requests to localhost and access the webcam.
Latency. The electron IPC is way faster than using web sockets and the ability to have node modules in the renderer makes some task actually feasible. I've worked on apps that were quite possible to do with electron but were completely out of question in more classic environments like Cordova or in Android/iOS web views.
Just remember that authentication and origin checking is completely up to the websocket server.
Any random page in a browser can talk to your websocket cross origin, and it's up to your server to check the "Origin" header to make sure it's actually your app on the other end.
Yes and no. Recently browsers started assuming that a response without CORS headers it unsafe unless from the same origin. So even though you can make a request if it fails preflight it will not even reach your server.
You can try this by opening a console on any webpage and trying to do fetch requests or add img tags to the page that are loading resources from localhost.
Or just use unix domain sockets and named pipes, and then you don't have users complaining that you've used some random port that they want to use for some reason.
But really for stuff like file system access just use the node APIs, don't shuffle this stuff through any hand rolled IPC.
Since bridging Node.js with the DOM is basically the whole point of Electron, it's a little tough for me to answer this question. Yes, there are things Electron apps need to do that you can't do from standard Chrome.
That obviously depends on what your Electron app wants to do.
Let's say you're writing an IDE in it. How would you invoke compilers & debuggers, cache filesystem/type information, state, etc. without breaking out of the browser sandbox somehow?
They would be amazed, as this sounds like incredibly advanced technology, and maybe disappointed when they find it was all about imaginary objects in an interactive projector.
It sure is. This is why Chrome apps and progressive web apps are great - they share the Chrome runtime and inherit its hardening, security properties and updates.
Many Electron apps should just be a PWA instead, and many actually are. Why would I want to install a desktop app for WhatsApp? It runs just fine in Chrome, and using More Tools -> Create shortcut..., you can even create a launcher entry that will launch the page in its own window.
Because of inability of PWA to write local files at desired locations (you can at best download a file), PWA's usefulness is limited as a desktop app replacement technology. The moment you allow rw local file access you are off to a security-fun-land.
IIRC there was a feud between Chrome developers who wanted raw file access and Firefox ones who didn't want it. W3C sided with FF, so we can't build proper desktop apps using PWA, even if WASM makes them quite fast these days. Now Chrome devs resuscitated the attempt with NFS API, so I'll grab my popcorn and watch their interaction one more time...
The vast majority of the work I do can be done off-line with files stored on disk, minus stuff that obviously needs connectivity (e.g. Slack). Writing text, writing code, reading/editing documents and spreadsheets, doing CAD (mechanical and electronics), etc. During the week I live in the city, but on weekends and occasionally for longer stretches of time I like to head out to our rural house for peace and quiet (and focused work). Over time, the number of applications that ought to work off-line has been slowly shrinking, whether it's because they insist on using cloud storage instead of local storage, or licensing checks, or whatever. It's really really disappointing, and I would personally be delighted if I could get work done without an Internet connection.
You can design a PWA that works offline with local files on disk already, by using the browser's file select dialogs. It's not necessary to give the app arbitrary access to the whole filesystem to get that functionality, which is what the parent is asking for.
No, you can't. You can open local files but not save them to desired locations, only download them as usual browser files. There are polyfills that mostly don't work; each browser has a different broken API for local file access and methods are often deprecated/removed.
Your browser provides its own UI for choosing the location to save downloaded files. This might not be ideal if you want to build your own file manager view into your app, but I don't think it's fair to say that your app is less capable just because it doesn't have that.
An example - you are using some web IDE (imagine a self-hosted version of VSCode). You have a few local files open in your browser, editing the code. Now you want to save them - you'd have to "redownload" them to save them. That's a highly suboptimal UX.
If you are actively working on the files, then you could just save them to the app's local storage. There is not necessarily a need to save them back to the same place you imported them from. When you are ready to export the project then you could have the app generate a zip file, or just push it directly to git or another app and skip the filesystem altogether.
Obviously this is not a great workflow for certain things like system administration tools that are specifically designed to work with the local machine's filesystem, but that's not really a good use case for PWAs in the first place.
Local storage is obviously not an option - imagine your project has a few gigabytes. Coding example was just to illustrate the problem quickly for everybody to understand what the issue is.
Forcing user to generate/download ZIP at some well-defined points in time is a horrible UX idea; in addition it leads to desynced content of files and local storage. Browser's local storage can also disappear if SQLite gets corrupted, making it a nice SPOF for all PWAs that are installed. Imagine not losing data just for one app, but for all of them.
I'm genuinely not all that familiar with what PWAs can and can't do... Would a, for example, Word-like PWA be able to both load and save files to disk?
Just like any web app, it would be able to read specific files of a user's choosing using an HTML "file" input, and it would be able to save files by initiating a download. The app would not be able to provide its own UI for selecting the file to open/save but rather it would have to rely on the browser's UI for doing those things.
As an example, if I were using a PWA-based schematic editor, I couldn't just hit Cmd-S and save it back to disk without having to choose the download location etc every time?
You would have to do that, unless you are willing to only save the data in the app's storage itself while you're working on it. Similar to the model typically used with mobile apps, for example.
How do I build installer for Chrome PWA? Like if user does not have Chrome, it should install it. Also i don't want to bother user with that implicitly installed chrome, so it should not add shortcuts, etc and just live as an app launcher.
Turns out a PWA works in Firefox too [1] so I'm not sure it's entirely necessary to force a user to install a browser just for your app. Edge is/will be chromium, so I guess Safari is the only major browser to worry about?
IMO you shouldn't have to make an installer, it should be the browser's job to expose the feature and integrate itself to the OS as natively as possible.
Because my Chrome already takes 6GB of memory and thus needs to be restarted once in a while. If those forces me to close apps I want to continue using then that will annoy me.
This needs to be distributable by the website... also with caching guarantees, desktop capture support (which I think is there now, but wasn't till just recently) etc.
Wonder if this exploit worked with the Mac App Store version of WhatsApp and the extra sandboxing layer(?) that whole ecosystem provides.
Out of sheer hope and ignorant superstition about the wonders of sandboxing, I tend to install the App Store versions of crap like WhatsApp and Slack whenever possible.
It would likely work for whatever directories you had granted it access to — otherwise, the situation is similar to that of iOS where the most an app has access to is its own container.
Good reason to not give apps full disk access unless they really, really need it even if it’s more convenient to do so.
Preview is generated on sender side, preview is generated on client side or preview is generated on some server.
On a "secure" system as Whatsapp is advertised as, you'll notice only the second choice is "secure" and possible, since otherwise you'll disclose both your IP and lots of other things, like location (from IP).
It's easy to under appreciate the amount of infrastructure work involved in deploying a production electron app to customers. Auto-updates, code signing, installers etc...
I think it is a good idea to containerize all electron apps, and run them only in containers. It is because reducing the surface area of your code to the system will reduce vulnerabilities of your code.
I never really thought about this, but in retrospect, this is so blindingly obvious, and is almost certainly a potential exploit vector to a wide range of electron-based apps.