kewde / electron-sandbox-boilerplate

A simple example for a (more reasonably) secure electron application, by enabling the sandbox and forcing communication over IPC.
MIT License
73 stars 14 forks source link

Sandbox-preload-extended Broken on latest Electron #14

Open drewwiens opened 6 years ago

drewwiens commented 6 years ago

Sandbox-preload-extended uses a preload script to attach functions to window. This no longer works in the latest Electron versions (at least >= 1.8) when you have either sandbox: true or contextIsolation: true in webPreferences, which is the case here.

I saw @kewde post here about it from a few weeks ago, so it seems like this is a known issue, but I didn't see anything about it in the issue tracker here.

Besides just pointing out that the example is broken, though, I was wondering if anyone knows how we are supposed to call Electron or Node APIs at all from a renderer process when either of these options (sandbox and contextIsolation) are turned on? If the preload script does not share the same window object as the page that's loaded, it seems like there is no way to do it...

What I am trying to achieve is an Electron app that 1) loads a remotely-hosted web app, and 2) is totally locked down security-wise except for a tiny hole punched between the renderer and the Node/Electron APIs where I can have my front-end call some native functionality.

kewde commented 6 years ago

After many days of research and fiddling with the IPC, I've concluded that the best way is to go the protocol route.

I will be deprecating this repository in favor of registerStreamProtocol. It allows you to set a custom protocol and communicate between the renderer & main.

Alternatively, you can use the chromium embedded framework, also known as CEF if you're comfortable with C++ and compiling Chromium on multiple operating systems. Additionally I suspect that libCEF ships with the additional (deprecated) setuid sandbox (it's useful as a fallback, when namespace sandbox support is disabled, https://github.com/brave/muon/issues/480 which occurs on Muon). CEF provides bindings to other languages too by the way - so you're not really restricted to C++.

If you want to stick with the Electron & NodeJS route, and use sandbox by default then take a look at Muon. It does not yet support the registerStreamProtocol (PR is there tho: https://github.com/brave/muon/pull/507). Perhaps you can run a local HTTP server and provide streaming data from there.

Also an API you might want to know of session.defaultSession.webRequest.onBeforeSendHeaders, you can hijack any outgoing HTTP(s) request (note that this does not prevent leakage in other ways, like WebRTC connections). But it does allow you to whitefilter and store authentication details on the backend (rather than passing them to the frontend). You can also block requests.

https://github.com/particl/particl-desktop/blob/market/modules/webrequest/http-auth.js#L21

reZach commented 4 years ago

@adwiens You can follow the steps outlined in a comment I posted.

This process is being followed in secure-electron-template that I am actively building.

kewde commented 4 years ago

@reZach Would you be interested in adding the information about verifying the sandbox to your repository so it doesn't get lost? this. I will replace the README with a notice forwarding people to your repo as this one is quite outdated. I'm glad to see so many people have taken an interest in the security of electron. Thank you

reZach commented 4 years ago

@kewde I would happily add that link to my repo, however the sandbox support is still experimental and am likely going to wait on implementing sandbox support until it's fully supported by the framework. My new template is essentially implementing sandbox, by only communicating via IPC, but this is implicit and not enforced by a setting on the BrowserWindow.

Wow, I'm honored, thanks!

reZach commented 4 years ago

@kewde I've created an issue in my repository linking to your page.