| 
									
										
										
										
											2017-03-09 09:23:03 -03:00
										 |  |  | # `sandbox` Option
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-21 14:41:53 +01:00
										 |  |  | > Create a browser window with a sandboxed renderer. With this
 | 
					
						
							| 
									
										
										
										
											2017-03-29 14:27:01 +01:00
										 |  |  | option enabled, the renderer must communicate via IPC to the main process in order to access node APIs. | 
					
						
							| 
									
										
										
										
											2017-03-09 09:23:03 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-29 14:27:01 +01:00
										 |  |  | One of the key security features of Chromium is that all blink rendering/JavaScript | 
					
						
							|  |  |  | code is executed within a sandbox. This sandbox uses OS-specific features to ensure | 
					
						
							| 
									
										
										
										
											2017-03-09 09:23:03 -03:00
										 |  |  | that exploits in the renderer process cannot harm the system. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | In other words, when the sandbox is enabled, the renderers can only make changes | 
					
						
							|  |  |  | to the system by delegating tasks to the main process via IPC. | 
					
						
							|  |  |  | [Here's](https://www.chromium.org/developers/design-documents/sandbox) more | 
					
						
							|  |  |  | information about the sandbox. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-20 14:58:19 -03:00
										 |  |  | Since a major feature in Electron is the ability to run Node.js in the | 
					
						
							| 
									
										
										
										
											2017-03-29 14:27:01 +01:00
										 |  |  | renderer process (making it easier to develop desktop applications using web | 
					
						
							|  |  |  | technologies), the sandbox is disabled by electron. This is because | 
					
						
							| 
									
										
										
										
											2018-07-20 14:58:19 -03:00
										 |  |  | most Node.js APIs require system access. `require()` for example, is not | 
					
						
							| 
									
										
										
										
											2017-03-29 14:27:01 +01:00
										 |  |  | possible without file system permissions, which are not available in a sandboxed | 
					
						
							| 
									
										
										
										
											2017-03-09 09:23:03 -03:00
										 |  |  | environment. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Usually this is not a problem for desktop applications since the code is always | 
					
						
							| 
									
										
										
										
											2018-07-20 14:58:19 -03:00
										 |  |  | trusted, but it makes Electron less secure than Chromium for displaying | 
					
						
							| 
									
										
										
										
											2017-03-09 09:23:03 -03:00
										 |  |  | untrusted web content. For applications that require more security, the | 
					
						
							| 
									
										
										
										
											2018-07-20 14:58:19 -03:00
										 |  |  | `sandbox` flag will force Electron to spawn a classic Chromium renderer that is | 
					
						
							| 
									
										
										
										
											2017-03-09 09:23:03 -03:00
										 |  |  | compatible with the sandbox. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-20 14:58:19 -03:00
										 |  |  | A sandboxed renderer doesn't have a Node.js environment running and doesn't | 
					
						
							|  |  |  | expose Node.js JavaScript APIs to client code. The only exception is the preload script, | 
					
						
							|  |  |  | which has access to a subset of the Electron renderer API. | 
					
						
							| 
									
										
										
										
											2017-03-09 09:23:03 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | Another difference is that sandboxed renderers don't modify any of the default | 
					
						
							| 
									
										
										
										
											2017-03-29 14:27:01 +01:00
										 |  |  | JavaScript APIs. Consequently, some APIs such as `window.open` will work as they | 
					
						
							| 
									
										
										
										
											2018-07-20 14:58:19 -03:00
										 |  |  | do in Chromium (i.e. they do not return a [`BrowserWindowProxy`](browser-window-proxy.md)). | 
					
						
							| 
									
										
										
										
											2017-03-09 09:23:03 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | ## Example
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-08 00:16:09 -05:00
										 |  |  | To create a sandboxed window, pass `sandbox: true` to `webPreferences`: | 
					
						
							| 
									
										
										
										
											2017-03-09 09:23:03 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | let win | 
					
						
							| 
									
										
										
										
											2020-02-03 16:43:22 -06:00
										 |  |  | app.whenReady().then(() => { | 
					
						
							| 
									
										
										
										
											2017-03-09 09:23:03 -03:00
										 |  |  |   win = new BrowserWindow({ | 
					
						
							|  |  |  |     webPreferences: { | 
					
						
							|  |  |  |       sandbox: true | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   }) | 
					
						
							| 
									
										
										
										
											2017-09-13 20:53:30 +00:00
										 |  |  |   win.loadURL('http://google.com') | 
					
						
							| 
									
										
										
										
											2017-03-09 09:23:03 -03:00
										 |  |  | }) | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-20 14:58:19 -03:00
										 |  |  | In the above code the [`BrowserWindow`](browser-window.md) 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`](browser-window.md) | 
					
						
							| 
									
										
										
										
											2017-03-29 14:27:01 +01:00
										 |  |  | and returns a proxy to this via `window.open`). | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-21 14:41:53 +01:00
										 |  |  | [`app.enableSandbox`](app.md#appenablesandbox-experimental) can be used to force `sandbox: true` for all `BrowserWindow` instances. | 
					
						
							| 
									
										
										
										
											2017-03-29 14:27:01 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-09 09:23:03 -03:00
										 |  |  | ```js | 
					
						
							|  |  |  | let win | 
					
						
							| 
									
										
										
										
											2019-03-21 14:41:53 +01:00
										 |  |  | app.enableSandbox() | 
					
						
							| 
									
										
										
										
											2020-02-03 16:43:22 -06:00
										 |  |  | app.whenReady().then(() => { | 
					
						
							| 
									
										
										
										
											2019-03-21 14:41:53 +01:00
										 |  |  |   // no need to pass `sandbox: true` since `app.enableSandbox()` was called. | 
					
						
							| 
									
										
										
										
											2017-03-09 09:23:03 -03:00
										 |  |  |   win = new BrowserWindow() | 
					
						
							| 
									
										
										
										
											2017-09-13 20:53:30 +00:00
										 |  |  |   win.loadURL('http://google.com') | 
					
						
							| 
									
										
										
										
											2017-03-09 09:23:03 -03:00
										 |  |  | }) | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## Preload
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | An app can make customizations to sandboxed renderers using a preload script. | 
					
						
							|  |  |  | Here's an example: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | let win | 
					
						
							| 
									
										
										
										
											2020-02-03 16:43:22 -06:00
										 |  |  | app.whenReady().then(() => { | 
					
						
							| 
									
										
										
										
											2017-03-09 09:23:03 -03:00
										 |  |  |   win = new BrowserWindow({ | 
					
						
							|  |  |  |     webPreferences: { | 
					
						
							|  |  |  |       sandbox: true, | 
					
						
							| 
									
										
										
										
											2019-03-28 11:38:51 +01:00
										 |  |  |       preload: path.join(app.getAppPath(), 'preload.js') | 
					
						
							| 
									
										
										
										
											2017-03-09 09:23:03 -03:00
										 |  |  |     } | 
					
						
							|  |  |  |   }) | 
					
						
							| 
									
										
										
										
											2017-09-13 20:53:30 +00:00
										 |  |  |   win.loadURL('http://google.com') | 
					
						
							| 
									
										
										
										
											2017-03-09 09:23:03 -03:00
										 |  |  | }) | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | and preload.js: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | // This file is loaded whenever a javascript context is created. It runs in a | 
					
						
							| 
									
										
										
										
											2018-07-20 14:58:19 -03:00
										 |  |  | // private scope that can access a subset of Electron renderer APIs. We must be | 
					
						
							| 
									
										
										
										
											2017-03-09 09:23:03 -03:00
										 |  |  | // careful to not leak any objects into the global scope! | 
					
						
							| 
									
										
										
										
											2019-03-21 14:41:53 +01:00
										 |  |  | const { ipcRenderer, remote } = require('electron') | 
					
						
							|  |  |  | const fs = remote.require('fs') | 
					
						
							| 
									
										
										
										
											2017-03-09 09:23:03 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | // read a configuration file using the `fs` module | 
					
						
							|  |  |  | const buf = fs.readFileSync('allowed-popup-urls.json') | 
					
						
							|  |  |  | const allowedUrls = JSON.parse(buf.toString('utf8')) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const defaultWindowOpen = window.open | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function customWindowOpen (url, ...args) { | 
					
						
							|  |  |  |   if (allowedUrls.indexOf(url) === -1) { | 
					
						
							|  |  |  |     ipcRenderer.sendSync('blocked-popup-notification', location.origin, url) | 
					
						
							|  |  |  |     return null | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return defaultWindowOpen(url, ...args) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | window.open = customWindowOpen | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Important things to notice in the preload script: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-20 14:58:19 -03:00
										 |  |  | - Even though the sandboxed renderer doesn't have Node.js running, it still has | 
					
						
							| 
									
										
										
										
											2019-05-20 17:34:57 +02:00
										 |  |  |   access to a limited node-like environment: `Buffer`, `process`, `setImmediate`, | 
					
						
							|  |  |  |   `clearImmediate` and `require` are available. | 
					
						
							| 
									
										
										
										
											2017-03-29 14:27:01 +01:00
										 |  |  | - The preload script can indirectly access all APIs from the main process through the | 
					
						
							| 
									
										
										
										
											2019-03-21 14:41:53 +01:00
										 |  |  |   `remote` and `ipcRenderer` modules. | 
					
						
							| 
									
										
										
										
											2017-03-29 14:27:01 +01:00
										 |  |  | - The preload script must be contained in a single script, but it is possible to have | 
					
						
							| 
									
										
										
										
											2017-03-09 09:23:03 -03:00
										 |  |  |   complex preload code composed with multiple modules by using a tool like | 
					
						
							| 
									
										
										
										
											2019-06-02 13:03:03 -07:00
										 |  |  |   webpack or browserify. An example of using browserify is below. | 
					
						
							| 
									
										
										
										
											2017-03-09 09:23:03 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | To create a browserify bundle and use it as a preload script, something like | 
					
						
							|  |  |  | the following should be used: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-20 14:18:24 +08:00
										 |  |  | ```sh | 
					
						
							|  |  |  |   browserify preload/index.js \ | 
					
						
							|  |  |  |     -x electron \ | 
					
						
							|  |  |  |     --insert-global-vars=__filename,__dirname -o preload.js | 
					
						
							|  |  |  | ``` | 
					
						
							| 
									
										
										
										
											2017-03-09 09:23:03 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 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 | 
					
						
							| 
									
										
										
										
											2017-03-29 14:27:01 +01:00
										 |  |  | for it. `--insert-global-vars` will ensure that `process`, `Buffer` and | 
					
						
							| 
									
										
										
										
											2017-03-09 09:23:03 -03:00
										 |  |  | `setImmediate` are also taken from the enclosing scope(normally browserify | 
					
						
							|  |  |  | injects code for those). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Currently the `require` function provided in the preload scope exposes the | 
					
						
							|  |  |  | following modules: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-08 17:10:44 -07:00
										 |  |  | - `electron` | 
					
						
							|  |  |  |   - `crashReporter` | 
					
						
							| 
									
										
										
										
											2019-03-21 14:41:53 +01:00
										 |  |  |   - `desktopCapturer` | 
					
						
							| 
									
										
										
										
											2017-08-08 17:10:44 -07:00
										 |  |  |   - `ipcRenderer` | 
					
						
							| 
									
										
										
										
											2019-03-21 14:41:53 +01:00
										 |  |  |   - `nativeImage` | 
					
						
							|  |  |  |   - `remote` | 
					
						
							| 
									
										
										
										
											2017-08-08 17:10:44 -07:00
										 |  |  |   - `webFrame` | 
					
						
							| 
									
										
										
										
											2019-03-21 14:41:53 +01:00
										 |  |  | - `events` | 
					
						
							| 
									
										
										
										
											2017-03-09 09:23:03 -03:00
										 |  |  | - `timers` | 
					
						
							|  |  |  | - `url` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-20 14:58:19 -03:00
										 |  |  | More may be added as needed to expose more Electron APIs in the sandbox, but any | 
					
						
							| 
									
										
										
										
											2017-03-09 09:23:03 -03:00
										 |  |  | module in the main process can already be used through | 
					
						
							|  |  |  | `electron.remote.require`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## Status
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-29 14:27:01 +01:00
										 |  |  | Please use the `sandbox` option with care, as it is still an experimental | 
					
						
							| 
									
										
										
										
											2017-03-09 09:23:03 -03:00
										 |  |  | feature. We are still not aware of the security implications of exposing some | 
					
						
							| 
									
										
										
										
											2018-07-20 14:58:19 -03:00
										 |  |  | Electron renderer APIs to the preload script, but here are some things to | 
					
						
							| 
									
										
										
										
											2017-03-09 09:23:03 -03:00
										 |  |  | consider before rendering untrusted content: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-20 17:34:57 +02:00
										 |  |  | - A preload script can accidentally leak privileged APIs to untrusted code, | 
					
						
							|  |  |  |   unless [`contextIsolation`](../tutorial/security.md#3-enable-context-isolation-for-remote-content) | 
					
						
							|  |  |  |   is also enabled. | 
					
						
							| 
									
										
										
										
											2017-03-09 09:23:03 -03:00
										 |  |  | - Some bug in V8 engine may allow malicious code to access the renderer preload | 
					
						
							|  |  |  |   APIs, effectively granting full access to the system through the `remote` | 
					
						
							| 
									
										
										
										
											2019-05-20 17:34:57 +02:00
										 |  |  |   module. Therefore, it is highly recommended to | 
					
						
							|  |  |  |   [disable the `remote` module](../tutorial/security.md#15-disable-the-remote-module). | 
					
						
							|  |  |  |   If disabling is not feasible, you should selectively | 
					
						
							|  |  |  |   [filter the `remote` module](../tutorial/security.md#16-filter-the-remote-module). | 
					
						
							| 
									
										
										
										
											2017-03-09 09:23:03 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-20 14:58:19 -03:00
										 |  |  | Since rendering untrusted content in Electron is still uncharted territory, | 
					
						
							| 
									
										
										
										
											2017-03-09 09:23:03 -03:00
										 |  |  | the APIs exposed to the sandbox preload script should be considered more | 
					
						
							| 
									
										
										
										
											2018-07-20 14:58:19 -03:00
										 |  |  | unstable than the rest of Electron APIs, and may have breaking changes to fix | 
					
						
							| 
									
										
										
										
											2017-03-09 09:23:03 -03:00
										 |  |  | security issues. |