Clarification of the chromium sandbox support

This commit is contained in:
Colin Eberhardt 2017-03-29 14:27:01 +01:00 committed by Colin Eberhardt
parent 57edc28b0d
commit bed32682b7

View file

@ -1,9 +1,12 @@
# `sandbox` Option # `sandbox` Option
> Create a browser window with renderer that can run inside chromium OS sandbox. > Create a browser window with a renderer that can run inside Chromium OS sandbox. With this
option enabled, the renderer must communicate via IPC to the main process in order to access node APIs.
However, in order to enable the Chromium OS sandbox, electron must be run with the `--enable-sandbox`
command line argument.
One of chromium key security features is that all blink rendering/javascript One of the key security features of Chromium is that all blink rendering/JavaScript
code is confined in a sandbox. This sandbox uses OS-specific features to ensure code is executed within a sandbox. This sandbox uses OS-specific features to ensure
that exploits in the renderer process cannot harm the system. that exploits in the renderer process cannot harm the system.
In other words, when the sandbox is enabled, the renderers can only make changes In other words, when the sandbox is enabled, the renderers can only make changes
@ -12,10 +15,10 @@ to the system by delegating tasks to the main process via IPC.
information about the sandbox. information about the sandbox.
Since a major feature in electron is the ability to run node.js in the Since a major feature in electron is the ability to run node.js in the
renderer process(making it easier to develop desktop applications using only web renderer process (making it easier to develop desktop applications using web
technologies), the sandbox has to disabled by electron. One of the reasons is technologies), the sandbox is disabled by electron. This is because
that most node.js APIs require system access. `require()` for example, is not most node.js APIs require system access. `require()` for example, is not
possible without file system permissions, which are unavailable in a sandboxed possible without file system permissions, which are not available in a sandboxed
environment. environment.
Usually this is not a problem for desktop applications since the code is always Usually this is not a problem for desktop applications since the code is always
@ -25,16 +28,16 @@ untrusted web content. For applications that require more security, the
compatible with the sandbox. compatible with the sandbox.
A sandboxed renderer doesn't have a node.js environment running and doesn't A sandboxed renderer doesn't have a node.js environment running and doesn't
expose javascript APIs to client code. The only exception is the preload script, expose node.js JavaScript APIs to client code. The only exception is the preload script,
which has access to a subset of electron renderer API. which has access to a subset of the electron renderer API.
Another difference is that sandboxed renderers don't modify any of the default Another difference is that sandboxed renderers don't modify any of the default
javascript APIs. Consequently, some APIs such as `window.open` will work as they JavaScript APIs. Consequently, some APIs such as `window.open` will work as they
do in chromium(no `BrowserWindowProxy`). do in chromium (i.e. they do not return a `BrowserWindowProxy`).
## Example ## Example
Create a sandboxed window, simply pass `sandbox: true` to `webPreferences`: To create a sandboxed window, simply pass `sandbox: true` to `webPreferences`:
```js ```js
let win let win
@ -48,9 +51,15 @@ app.on('ready', () => {
}) })
``` ```
This alone won't enable the OS-enforced sandbox. To use it, the In the above code the `BrowserWindow` that was created has node.js disabled and can communicate
only via IPC. The use of this option stops electron from creating a node.js runtime in the renderer. Also,
within this new window `window.open` follows the native behaviour (by default electron creates a `BrowserWindow`
and returns a proxy to this via `window.open`).
It is important to note that this option alone won't enable the OS-enforced sandbox. To enable this feature, the
`--enable-sandbox` command-line argument must be passed to electron, which will `--enable-sandbox` command-line argument must be passed to electron, which will
force `sandbox: true` to all BrowserWindow instances. force `sandbox: true` for all `BrowserWindow` instances.
```js ```js
let win let win
@ -64,7 +73,7 @@ app.on('ready', () => {
Note that it is not enough to call Note that it is not enough to call
`app.commandLine.appendSwitch('--enable-sandbox')`, as electron/node startup `app.commandLine.appendSwitch('--enable-sandbox')`, as electron/node startup
code runs after it is possible to make changes to chromium sandbox settings. The code runs after it is possible to make changes to chromium sandbox settings. The
switch must be passed to electron command-line: switch must be passed to electron on the command-line:
``` ```
electron --enable-sandbox app.js electron --enable-sandbox app.js
@ -125,16 +134,16 @@ window.open = customWindowOpen
Important things to notice in the preload script: Important things to notice in the preload script:
- Even though the sandboxed renderer doesn't have node.js running, it still has - Even though the sandboxed renderer doesn't have node.js running, it still has
access to a limited node-like environment:`Buffer`, `process`, `setImmediate` access to a limited node-like environment: `Buffer`, `process`, `setImmediate`
and `require` are available. and `require` are available.
- The preload can indirectly access all APIs from the main process through the - The preload script can indirectly access all APIs from the main process through the
`remote` and `ipcRenderer` modules. This is how `fs`(used above) and other `remote` and `ipcRenderer` modules. This is how `fs` (used above) and other
modules are implemented: They are proxies to remote counterparts in the main modules are implemented: They are proxies to remote counterparts in the main
process. process.
- The preload must be contained in a single script, but it is possible to have - The preload script must be contained in a single script, but it is possible to have
complex preload code composed with multiple modules by using a tool like complex preload code composed with multiple modules by using a tool like
browserify, as explained below. In fact, browserify is already used by browserify, as explained below. In fact, browserify is already used by
electron to provide a node-like environment to the preload script. electron to provide a node-like environment to the preload script.
To create a browserify bundle and use it as a preload script, something like To create a browserify bundle and use it as a preload script, something like
the following should be used: the following should be used:
@ -146,7 +155,7 @@ the following should be used:
The `-x` flag should be used with any required module that is already exposed in The `-x` flag should be used with any required module that is already exposed in
the preload scope, and tells browserify to use the enclosing `require` function the preload scope, and tells browserify to use the enclosing `require` function
for it. `--insert-global-vars` will ensure that `process`,`Buffer` and for it. `--insert-global-vars` will ensure that `process`, `Buffer` and
`setImmediate` are also taken from the enclosing scope(normally browserify `setImmediate` are also taken from the enclosing scope(normally browserify
injects code for those). injects code for those).
@ -154,7 +163,7 @@ Currently the `require` function provided in the preload scope exposes the
following modules: following modules:
- `child_process` - `child_process`
- `electron`(crashReporter, remote and ipcRenderer) - `electron` (crashReporter, remote and ipcRenderer)
- `fs` - `fs`
- `os` - `os`
- `timers` - `timers`
@ -166,7 +175,7 @@ module in the main process can already be used through
## Status ## Status
Please use the `sandbox` option with care, as it still is an experimental Please use the `sandbox` option with care, as it is still an experimental
feature. We are still not aware of the security implications of exposing some feature. We are still not aware of the security implications of exposing some
electron renderer APIs to the preload script, but here are some things to electron renderer APIs to the preload script, but here are some things to
consider before rendering untrusted content: consider before rendering untrusted content:
@ -176,11 +185,11 @@ consider before rendering untrusted content:
APIs, effectively granting full access to the system through the `remote` APIs, effectively granting full access to the system through the `remote`
module. module.
Since renderering untrusted content in electron is still uncharted territory, Since rendering untrusted content in electron is still uncharted territory,
the APIs exposed to the sandbox preload script should be considered more the APIs exposed to the sandbox preload script should be considered more
unstable than the rest of electron APIs, and may have breaking changes to fix unstable than the rest of electron APIs, and may have breaking changes to fix
security issues. security issues.
One planned enhancement that should greatly increase security is to block IPC One planned enhancement that should greatly increase security is to block IPC
messages from sandboxed renderers by default, allowing the main process messages from sandboxed renderers by default, allowing the main process to
explicitly define a set of messages the renderer is allowed to send. explicitly define a set of messages the renderer is allowed to send.