|
@@ -0,0 +1,169 @@
|
|
|
+# Process Sandboxing
|
|
|
+
|
|
|
+One key security feature in Chromium is that processes can be executed within a sandbox.
|
|
|
+The sandbox limits the harm that malicious code can cause by limiting access to most
|
|
|
+system resources — sandboxed processes can only freely use CPU cycles and memory.
|
|
|
+In order to perform operations requiring additional privilege, sandboxed processes
|
|
|
+use dedicated communication channels to delegate tasks to more privileged processes.
|
|
|
+
|
|
|
+In Chromium, sandboxing is applied to most processes other than the main process.
|
|
|
+This includes renderer processes, as well as utility processes such as the audio service,
|
|
|
+the GPU service and the network service.
|
|
|
+
|
|
|
+See Chromium's [Sandbox design document][sandbox] for more information.
|
|
|
+
|
|
|
+## Electron's sandboxing policies
|
|
|
+
|
|
|
+Electron comes with a mixed sandbox environment, meaning sandboxed processes can run
|
|
|
+alongside privileged ones. By default, renderer processes are not sandboxed, but
|
|
|
+utility processes are. Note that as in Chromium, the main (browser) process is
|
|
|
+privileged and cannot be sandboxed.
|
|
|
+
|
|
|
+Historically, this mixed sandbox approach was established because having Node.js available
|
|
|
+in the renderer is an extremely powerful tool for app developers. Unfortunately, this
|
|
|
+feature is also an equally massive security vulnerability.
|
|
|
+
|
|
|
+Theoretically, unsandboxed renderers are not a problem for desktop applications that
|
|
|
+only display trusted code, but they make Electron less secure than Chromium for
|
|
|
+displaying untrusted web content. However, even purportedly trusted code may be
|
|
|
+dangerous — there are countless attack vectors that malicious actors can use, from
|
|
|
+cross-site scripting to content injection to man-in-the-middle attacks on remotely loaded
|
|
|
+websites, just to name a few. For this reason, we recommend enabling renderer sandboxing
|
|
|
+for the vast majority of cases under an abundance of caution.
|
|
|
+
|
|
|
+<!--TODO: update this guide when #28466 is either solved or closed -->
|
|
|
+Note that there is an active discussion in the issue tracker to enable renderer sandboxing
|
|
|
+by default. See [#28466][issue-28466]) for details.
|
|
|
+
|
|
|
+## Sandbox behaviour in Electron
|
|
|
+
|
|
|
+Sandboxed processes in Electron behave _mostly_ in the same way as Chromium's do, but
|
|
|
+Electron has a few additional concepts to consider because it interfaces with Node.js.
|
|
|
+
|
|
|
+### Renderer processes
|
|
|
+
|
|
|
+When renderer processes in Electron are sandboxed, they behave in the same way as a
|
|
|
+regular Chrome renderer would. A sandboxed renderer won't have a Node.js
|
|
|
+environment initialized.
|
|
|
+
|
|
|
+<!-- TODO(erickzhao): when we have a solid guide for IPC, link it here -->
|
|
|
+Therefore, when the sandbox is enabled, renderer processes can only perform privileged
|
|
|
+tasks (such as interacting with the filesystem, making changes to the system, or spawning
|
|
|
+subprocesses) by delegating these tasks to the main process via inter-process
|
|
|
+communication (IPC).
|
|
|
+
|
|
|
+### Preload scripts
|
|
|
+
|
|
|
+In order to allow renderer processes to communicate with the main process, preload
|
|
|
+scripts attached to sandboxed renderers will still have a polyfilled subset of Node.js
|
|
|
+APIs available. A `require` function similar to Node's `require` module is exposed,
|
|
|
+but can only import a subset of Electron and Node's built-in modules:
|
|
|
+
|
|
|
+* `electron` (only renderer process modules)
|
|
|
+* [`events`](https://nodejs.org/api/events.html)
|
|
|
+* [`timers`](https://nodejs.org/api/timers.html)
|
|
|
+* [`url`](https://nodejs.org/api/url.html)
|
|
|
+
|
|
|
+In addition, the preload script also polyfills certain Node.js primitives as globals:
|
|
|
+
|
|
|
+* [`Buffer`](https://nodejs.org/api/Buffer.html)
|
|
|
+* [`process`](../api/process.md)
|
|
|
+* [`clearImmediate`](https://nodejs.org/api/timers.html#timers_clearimmediate_immediate)
|
|
|
+* [`setImmediate`](https://nodejs.org/api/timers.html#timers_setimmediate_callback_args)
|
|
|
+
|
|
|
+Because the `require` function is a polyfill with limited functionality, you will not be
|
|
|
+able to use [CommonJS modules][commonjs] to separate your preload script into multiple
|
|
|
+files. If you need to split your preload code, use a bundler such as [webpack][webpack]
|
|
|
+or [Parcel][parcel].
|
|
|
+
|
|
|
+Note that because the environment presented to the `preload` script is substantially
|
|
|
+more privileged than that of a sandboxed renderer, it is still possible to leak
|
|
|
+privileged APIs to untrusted code running in the renderer process unless
|
|
|
+[`contextIsolation`][contextIsolation] is enabled.
|
|
|
+
|
|
|
+## Configuring the sandbox
|
|
|
+
|
|
|
+### Enabling the sandbox for a single process
|
|
|
+
|
|
|
+In Electron, renderer sandboxing can be enabled on a per-process basis with
|
|
|
+the `sandbox: true` preference in the [`BrowserWindow`][browser-window] constructor.
|
|
|
+
|
|
|
+```js
|
|
|
+// main.js
|
|
|
+app.whenReady().then(() => {
|
|
|
+ const win = new BrowserWindow({
|
|
|
+ webPreferences: {
|
|
|
+ sandbox: true
|
|
|
+ }
|
|
|
+ })
|
|
|
+ win.loadURL('https://google.com')
|
|
|
+})
|
|
|
+```
|
|
|
+
|
|
|
+### Enabling the sandbox globally
|
|
|
+
|
|
|
+If you want to force sandboxing for all renderers, you can also use the
|
|
|
+[`app.enableSandbox`][enable-sandbox] API. Note that this API has to be called before the
|
|
|
+app's `ready` event.
|
|
|
+
|
|
|
+```js
|
|
|
+// main.js
|
|
|
+app.enableSandbox()
|
|
|
+app.whenReady().then(() => {
|
|
|
+ // no need to pass `sandbox: true` since `app.enableSandbox()` was called.
|
|
|
+ const win = new BrowserWindow()
|
|
|
+ win.loadURL('https://google.com')
|
|
|
+})
|
|
|
+```
|
|
|
+
|
|
|
+### Disabling Chromium's sandbox (testing only)
|
|
|
+
|
|
|
+You can also disable Chromium's sandbox entirely with the [`--no-sandbox`][no-sandbox]
|
|
|
+CLI flag, which will disable the sandbox for all processes (including utility processes).
|
|
|
+We highly recommend that you only use this flag for testing purposes, and **never**
|
|
|
+in production.
|
|
|
+
|
|
|
+Note that the `sandbox: true` option will still disable the renderer's Node.js
|
|
|
+environment.
|
|
|
+
|
|
|
+## A note on rendering untrusted content
|
|
|
+
|
|
|
+Rendering untrusted content in Electron is still somewhat uncharted territory,
|
|
|
+though some apps are finding success (e.g. [Beaker Browser][beaker]).
|
|
|
+Our goal is to get as close to Chrome as we can in terms of the security of
|
|
|
+sandboxed content, but ultimately we will always be behind due to a few fundamental
|
|
|
+issues:
|
|
|
+
|
|
|
+1. We do not have the dedicated resources or expertise that Chromium has to
|
|
|
+ apply to the security of its product. We do our best to make use of what we
|
|
|
+ have, to inherit everything we can from Chromium, and to respond quickly to
|
|
|
+ security issues, but Electron cannot be as secure as Chromium without the
|
|
|
+ resources that Chromium is able to dedicate.
|
|
|
+2. Some security features in Chrome (such as Safe Browsing and Certificate
|
|
|
+ Transparency) require a centralized authority and dedicated servers, both of
|
|
|
+ which run counter to the goals of the Electron project. As such, we disable
|
|
|
+ those features in Electron, at the cost of the associated security they
|
|
|
+ would otherwise bring.
|
|
|
+3. There is only one Chromium, whereas there are many thousands of apps built
|
|
|
+ on Electron, all of which behave slightly differently. Accounting for those
|
|
|
+ differences can yield a huge possibility space, and make it challenging to
|
|
|
+ ensure the security of the platform in unusual use cases.
|
|
|
+4. We can't push security updates to users directly, so we rely on app vendors
|
|
|
+ to upgrade the version of Electron underlying their app in order for
|
|
|
+ security updates to reach users.
|
|
|
+
|
|
|
+While we make our best effort to backport Chromium security fixes to older
|
|
|
+versions of Electron, we do not make a guarantee that every fix will be
|
|
|
+backported. Your best chance at staying secure is to be on the latest stable
|
|
|
+version of Electron.
|
|
|
+
|
|
|
+[sandbox]: https://chromium.googlesource.com/chromium/src/+/master/docs/design/sandbox.md
|
|
|
+[issue-28466]: https://github.com/electron/electron/issues/28466
|
|
|
+[browser-window]: ../api/browser-window.md
|
|
|
+[enable-sandbox]: ../api/app.md#appenablesandbox
|
|
|
+[no-sandbox]: ../api/command-line-switches.md#--no-sandbox
|
|
|
+[commonjs]: https://nodejs.org/api/modules.html#modules_modules_commonjs_modules
|
|
|
+[webpack]: https://webpack.js.org/
|
|
|
+[parcel]: https://parceljs.org/
|
|
|
+[context-isolation]: ./context-isolation.md
|
|
|
+[beaker]: https://github.com/beakerbrowser/beaker
|