Skip to content

Commit

Permalink
docs: rework sandbox guide (#28978)
Browse files Browse the repository at this point in the history
* docs: rework sandbox guide

* update doc name

* add missing comment to code sample

* Update docs/tutorial/sandbox.md

Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>

* Update docs/tutorial/sandbox.md

Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>

* Update docs/tutorial/sandbox.md

Co-authored-by: Biru Mohanathas <birunthan@mohanathas.com>

* load https in the examples

* change `process` docs to Electron's

* remove bit on chrome://sandbox page

* Update docs/tutorial/sandbox.md

Co-authored-by: Jeremy Rose <nornagon@nornagon.net>

* Update docs/tutorial/sandbox.md

Co-authored-by: Jeremy Rose <nornagon@nornagon.net>

* clarify sandbox default posture

* clarify tasks sandboxed renderers need ipc for

* clarify polyfilled preload environment

* emphasize that --no-sandbox is bad

* clarify preload polyfill `require`

* format markdown references properly

Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
Co-authored-by: Biru Mohanathas <birunthan@mohanathas.com>
Co-authored-by: Jeremy Rose <nornagon@nornagon.net>
  • Loading branch information
4 people committed May 6, 2021
1 parent a264fc8 commit 8f87086
Show file tree
Hide file tree
Showing 7 changed files with 174 additions and 186 deletions.
1 change: 1 addition & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ an issue:
* [Using Native Node.js Modules](tutorial/using-native-node-modules.md)
* [Performance Strategies](tutorial/performance.md)
* [Security Strategies](tutorial/security.md)
* [Process Sandboxing](tutorial/sandbox.md)
* [Accessibility](tutorial/accessibility.md)
* [Manually Enabling Accessibility Features](tutorial/accessibility.md#manually-enabling-accessibility-features)
* [Testing and Debugging](tutorial/application-debugging.md)
Expand Down
2 changes: 1 addition & 1 deletion docs/api/browser-window.md
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
associated with the window, making it compatible with the Chromium
OS-level sandbox and disabling the Node.js engine. This is not the same as
the `nodeIntegration` option and the APIs available to the preload script
are more limited. Read more about the option [here](sandbox-option.md).
are more limited. Read more about the option [here](../tutorial/sandbox.md).
* `session` [Session](session.md#class-session) (optional) - Sets the session used by the
page. Instead of passing the Session object directly, you can also choose to
use the `partition` option instead, which accepts a partition string. When
Expand Down
3 changes: 2 additions & 1 deletion docs/api/command-line-switches.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,8 @@ proxy server flags that are passed.

### --no-sandbox

Disables Chromium sandbox, which is now enabled by default.
Disables the Chromium [sandbox](https://www.chromium.org/developers/design-documents/sandbox).
Forces renderer process and Chromium helper processes to run un-sandboxed.
Should only be used for testing.

### --proxy-bypass-list=`hosts`
Expand Down
182 changes: 0 additions & 182 deletions docs/api/sandbox-option.md

This file was deleted.

169 changes: 169 additions & 0 deletions docs/tutorial/sandbox.md
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion docs/tutorial/security.md
Original file line number Diff line number Diff line change
Expand Up @@ -692,5 +692,5 @@ which potential security issues are not as widely known.
[window-open-handler]: ../api/web-contents.md#contentssetwindowopenhandlerhandler
[will-navigate]: ../api/web-contents.md#event-will-navigate
[open-external]: ../api/shell.md#shellopenexternalurl-options
[sandbox]: ../api/sandbox-option.md
[sandbox]: ../tutorial/sandbox.md
[responsible-disclosure]: https://en.wikipedia.org/wiki/Responsible_disclosure
1 change: 0 additions & 1 deletion filenames.auto.gni
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ auto_filenames = {
"docs/api/power-save-blocker.md",
"docs/api/process.md",
"docs/api/protocol.md",
"docs/api/sandbox-option.md",
"docs/api/screen.md",
"docs/api/service-workers.md",
"docs/api/session.md",
Expand Down

0 comments on commit 8f87086

Please sign in to comment.