| 
									
										
										
										
											2016-05-06 11:23:18 +01:00
										 |  |  |  | # Security, Native Capabilities, and Your Responsibility
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-29 11:19:43 -08:00
										 |  |  |  | As web developers, we usually enjoy the strong security net of the browser - | 
					
						
							|  |  |  |  | the risks associated with the code we write are relatively small. Our websites | 
					
						
							|  |  |  |  | are granted limited powers in a sandbox, and we trust that our users enjoy a | 
					
						
							|  |  |  |  | browser built by a large team of engineers that is able to quickly respond to | 
					
						
							|  |  |  |  | newly discovered security threats. | 
					
						
							| 
									
										
										
										
											2016-05-06 11:23:18 +01:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-08 11:21:11 -07:00
										 |  |  |  | When working with Electron, it is important to understand that Electron is not | 
					
						
							|  |  |  |  | a web browser. It allows you to build feature-rich desktop applications with | 
					
						
							|  |  |  |  | familiar web technologies, but your code wields much greater power. JavaScript | 
					
						
							| 
									
										
										
										
											2016-06-01 06:36:45 +01:00
										 |  |  |  | can access the filesystem, user shell, and more. This allows you to build | 
					
						
							| 
									
										
										
										
											2018-01-29 11:19:43 -08:00
										 |  |  |  | high quality native applications, but the inherent security risks scale with | 
					
						
							|  |  |  |  | the additional powers granted to your code. | 
					
						
							| 
									
										
										
										
											2016-05-06 11:23:18 +01:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-29 16:01:05 -08:00
										 |  |  |  | With that in mind, be aware that displaying arbitrary content from untrusted | 
					
						
							| 
									
										
										
										
											2016-05-08 11:21:11 -07:00
										 |  |  |  | sources poses a severe security risk that Electron is not intended to handle. | 
					
						
							| 
									
										
										
										
											2016-05-10 17:41:16 +09:00
										 |  |  |  | In fact, the most popular Electron apps (Atom, Slack, Visual Studio Code, etc) | 
					
						
							|  |  |  |  | display primarily local content (or trusted, secure remote content without Node | 
					
						
							|  |  |  |  | integration) – if your application executes code from an online source, it is | 
					
						
							|  |  |  |  | your responsibility to ensure that the code is not malicious. | 
					
						
							| 
									
										
										
										
											2016-05-06 11:23:18 +01:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-30 10:57:53 -08:00
										 |  |  |  | ## Reporting Security Issues
 | 
					
						
							| 
									
										
										
										
											2017-01-30 10:49:17 -08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | For information on how to properly disclose an Electron vulnerability, | 
					
						
							|  |  |  |  | see [SECURITY.md](https://github.com/electron/electron/tree/master/SECURITY.md) | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-06 11:23:18 +01:00
										 |  |  |  | ## Chromium Security Issues and Upgrades
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-20 09:45:25 -07:00
										 |  |  |  | Electron keeps up to date with alternating Chromium releases. For more information, | 
					
						
							|  |  |  |  | see the [Electron Release Cadence blog post](https://electronjs.org/blog/12-week-cadence). | 
					
						
							| 
									
										
										
										
											2016-05-06 11:23:18 +01:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-27 19:09:38 +01:00
										 |  |  |  | ## Security Is Everyone's Responsibility
 | 
					
						
							| 
									
										
										
										
											2016-09-08 10:39:29 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-27 19:09:38 +01:00
										 |  |  |  | It is important to remember that the security of your Electron application is | 
					
						
							|  |  |  |  | the result of the overall security of the framework foundation | 
					
						
							|  |  |  |  | (*Chromium*, *Node.js*), Electron itself, all NPM dependencies and | 
					
						
							|  |  |  |  | your code. As such, it is your responsibility to follow a few important best | 
					
						
							|  |  |  |  | practices: | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-20 21:12:47 +01:00
										 |  |  |  | * **Keep your application up-to-date with the latest Electron framework release.** | 
					
						
							|  |  |  |  | When releasing your product, you’re also shipping a bundle composed of Electron, | 
					
						
							|  |  |  |  | Chromium shared library and Node.js. Vulnerabilities affecting these components | 
					
						
							|  |  |  |  | may impact the security of your application. By updating Electron to the latest | 
					
						
							|  |  |  |  | version, you ensure that critical vulnerabilities (such as *nodeIntegration bypasses*) | 
					
						
							| 
									
										
										
										
											2019-09-13 21:12:14 -04:00
										 |  |  |  | are already patched and cannot be exploited in your application. For more information, | 
					
						
							|  |  |  |  | see "[Use a current version of Electron](#17-use-a-current-version-of-electron)". | 
					
						
							| 
									
										
										
										
											2019-02-27 19:09:38 +01:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-20 21:12:47 +01:00
										 |  |  |  | * **Evaluate your dependencies.** While NPM provides half a million reusable packages, | 
					
						
							|  |  |  |  | it is your responsibility to choose trusted 3rd-party libraries. If you use outdated | 
					
						
							|  |  |  |  | libraries affected by known vulnerabilities or rely on poorly maintained code, | 
					
						
							| 
									
										
										
										
											2019-02-27 19:09:38 +01:00
										 |  |  |  | your application security could be in jeopardy. | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-20 21:12:47 +01:00
										 |  |  |  | * **Adopt secure coding practices.** The first line of defense for your application | 
					
						
							|  |  |  |  | is your own code. Common web vulnerabilities, such as Cross-Site Scripting (XSS), | 
					
						
							|  |  |  |  | have a higher security impact on Electron applications hence it is highly recommended | 
					
						
							| 
									
										
										
										
											2019-02-27 19:09:38 +01:00
										 |  |  |  | to adopt secure software development best practices and perform security testing. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ## Isolation For Untrusted Content
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | A security issue exists whenever you receive code from an untrusted source (e.g. | 
					
						
							|  |  |  |  | a remote server) and execute it locally. As an example, consider a remote | 
					
						
							|  |  |  |  | website being displayed inside a default [`BrowserWindow`][browser-window]. If | 
					
						
							|  |  |  |  | an attacker somehow manages to change said content (either by attacking the | 
					
						
							|  |  |  |  | source directly, or by sitting between your app and the actual destination), they | 
					
						
							|  |  |  |  | will be able to execute native code on the user's machine. | 
					
						
							| 
									
										
										
										
											2016-05-06 11:23:18 +01:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-10 17:41:16 +09:00
										 |  |  |  | > :warning: Under no circumstances should you load and execute remote code with
 | 
					
						
							| 
									
										
										
										
											2018-01-29 11:19:43 -08:00
										 |  |  |  | Node.js integration enabled. Instead, use only local files (packaged together | 
					
						
							|  |  |  |  | with your application) to execute Node.js code. To display remote content, use | 
					
						
							| 
									
										
										
										
											2019-02-27 19:09:38 +01:00
										 |  |  |  | the [`<webview>`][webview-tag] tag or [`BrowserView`][browser-view], make sure | 
					
						
							|  |  |  |  | to disable the `nodeIntegration` and enable `contextIsolation`. | 
					
						
							| 
									
										
										
										
											2016-05-06 11:23:18 +01:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-03 06:50:12 -08:00
										 |  |  |  | ## Electron Security Warnings
 | 
					
						
							| 
									
										
										
										
											2016-09-08 10:39:29 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-03 06:50:12 -08:00
										 |  |  |  | From Electron 2.0 on, developers will see warnings and recommendations printed | 
					
						
							| 
									
										
										
										
											2018-02-26 04:11:18 +13:00
										 |  |  |  | to the developer console. They only show up when the binary's name is Electron, | 
					
						
							| 
									
										
										
										
											2018-02-03 06:50:12 -08:00
										 |  |  |  | indicating that a developer is currently looking at the console. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | You can force-enable or force-disable these warnings by setting | 
					
						
							|  |  |  |  | `ELECTRON_ENABLE_SECURITY_WARNINGS` or `ELECTRON_DISABLE_SECURITY_WARNINGS` on | 
					
						
							|  |  |  |  | either `process.env` or the `window` object. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ## Checklist: Security Recommendations
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-27 19:09:38 +01:00
										 |  |  |  | You should at least follow these steps to improve the security of your application: | 
					
						
							| 
									
										
										
										
											2016-05-06 11:23:18 +01:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-02 10:33:07 -05:00
										 |  |  |  | 1. [Only load secure content](#1-only-load-secure-content) | 
					
						
							| 
									
										
										
										
											2019-04-29 23:29:27 +02:00
										 |  |  |  | 2. [Disable the Node.js integration in all renderers that display remote content](#2-do-not-enable-nodejs-integration-for-remote-content) | 
					
						
							| 
									
										
										
										
											2018-05-02 19:51:37 -07:00
										 |  |  |  | 3. [Enable context isolation in all renderers that display remote content](#3-enable-context-isolation-for-remote-content) | 
					
						
							|  |  |  |  | 4. [Use `ses.setPermissionRequestHandler()` in all sessions that load remote content](#4-handle-session-permission-requests-from-remote-content) | 
					
						
							|  |  |  |  | 5. [Do not disable `webSecurity`](#5-do-not-disable-websecurity) | 
					
						
							|  |  |  |  | 6. [Define a `Content-Security-Policy`](#6-define-a-content-security-policy) and use restrictive rules (i.e. `script-src 'self'`) | 
					
						
							| 
									
										
										
										
											2018-11-12 11:13:48 -05:00
										 |  |  |  | 7. [Do not set `allowRunningInsecureContent` to `true`](#7-do-not-set-allowrunninginsecurecontent-to-true) | 
					
						
							|  |  |  |  | 8. [Do not enable experimental features](#8-do-not-enable-experimental-features) | 
					
						
							|  |  |  |  | 9. [Do not use `enableBlinkFeatures`](#9-do-not-use-enableblinkfeatures) | 
					
						
							|  |  |  |  | 10. [`<webview>`: Do not use `allowpopups`](#10-do-not-use-allowpopups) | 
					
						
							|  |  |  |  | 11. [`<webview>`: Verify options and params](#11-verify-webview-options-before-creation) | 
					
						
							|  |  |  |  | 12. [Disable or limit navigation](#12-disable-or-limit-navigation) | 
					
						
							|  |  |  |  | 13. [Disable or limit creation of new windows](#13-disable-or-limit-creation-of-new-windows) | 
					
						
							| 
									
										
										
										
											2019-02-27 19:09:38 +01:00
										 |  |  |  | 14. [Do not use `openExternal` with untrusted content](#14-do-not-use-openexternal-with-untrusted-content) | 
					
						
							| 
									
										
										
										
											2019-04-05 20:41:05 +02:00
										 |  |  |  | 15. [Disable the `remote` module](#15-disable-the-remote-module) | 
					
						
							|  |  |  |  | 16. [Filter the `remote` module](#16-filter-the-remote-module) | 
					
						
							| 
									
										
										
										
											2019-09-13 21:12:14 -04:00
										 |  |  |  | 17. [Use a current version of Electron](#17-use-a-current-version-of-electron) | 
					
						
							| 
									
										
										
										
											2019-02-27 19:09:38 +01:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | To automate the detection of misconfigurations and insecure patterns, it is | 
					
						
							|  |  |  |  | possible to use | 
					
						
							|  |  |  |  | [electronegativity](https://github.com/doyensec/electronegativity). For | 
					
						
							|  |  |  |  | additional details on potential weaknesses and implementation bugs when | 
					
						
							|  |  |  |  | developing applications using Electron, please refer to this [guide for | 
					
						
							|  |  |  |  | developers and auditors](https://doyensec.com/resources/us-17-Carettoni-Electronegativity-A-Study-Of-Electron-Security-wp.pdf) | 
					
						
							| 
									
										
										
										
											2018-01-29 11:19:43 -08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-01 09:58:02 -08:00
										 |  |  |  | ## 1) Only Load Secure Content
 | 
					
						
							| 
									
										
										
										
											2018-01-29 11:19:43 -08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | Any resources not included with your application should be loaded using a | 
					
						
							| 
									
										
										
										
											2018-01-29 12:34:46 -08:00
										 |  |  |  | secure protocol like `HTTPS`. In other words, do not use insecure protocols | 
					
						
							| 
									
										
										
										
											2018-02-13 00:18:27 -05:00
										 |  |  |  | like `HTTP`. Similarly, we recommend the use of `WSS` over `WS`, `FTPS` over | 
					
						
							| 
									
										
										
										
											2018-01-29 16:01:05 -08:00
										 |  |  |  | `FTP`, and so on. | 
					
						
							| 
									
										
										
										
											2018-01-28 16:55:11 -08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-28 17:25:05 -08:00
										 |  |  |  | ### Why?
 | 
					
						
							| 
									
										
										
										
											2018-01-29 11:19:43 -08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-28 16:55:11 -08:00
										 |  |  |  | `HTTPS` has three main benefits: | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-29 16:01:05 -08:00
										 |  |  |  | 1) It authenticates the remote server, ensuring your app connects to the correct | 
					
						
							|  |  |  |  |    host instead of an impersonator. | 
					
						
							| 
									
										
										
										
											2018-01-28 17:25:05 -08:00
										 |  |  |  | 2) It ensures data integrity, asserting that the data was not modified while in | 
					
						
							|  |  |  |  |    transit between your application and the host. | 
					
						
							| 
									
										
										
										
											2018-01-29 16:01:05 -08:00
										 |  |  |  | 3) It encrypts the traffic between your user and the destination host, making it | 
					
						
							|  |  |  |  |    more difficult to eavesdrop on the information sent between your app and | 
					
						
							| 
									
										
										
										
											2018-01-28 17:25:05 -08:00
										 |  |  |  |    the host. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ### How?
 | 
					
						
							| 
									
										
										
										
											2018-01-29 11:19:43 -08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-28 16:55:11 -08:00
										 |  |  |  | ```js | 
					
						
							|  |  |  |  | // Bad | 
					
						
							| 
									
										
										
										
											2019-02-27 19:09:38 +01:00
										 |  |  |  | browserWindow.loadURL('http://example.com') | 
					
						
							| 
									
										
										
										
											2018-01-28 16:55:11 -08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | // Good | 
					
						
							| 
									
										
										
										
											2019-02-27 19:09:38 +01:00
										 |  |  |  | browserWindow.loadURL('https://example.com') | 
					
						
							| 
									
										
										
										
											2018-01-28 16:55:11 -08:00
										 |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ```html | 
					
						
							|  |  |  |  | <!-- Bad --> | 
					
						
							| 
									
										
										
										
											2019-02-27 19:09:38 +01:00
										 |  |  |  | <script crossorigin src="http://example.com/react.js"></script> | 
					
						
							|  |  |  |  | <link rel="stylesheet" href="http://example.com/style.css"> | 
					
						
							| 
									
										
										
										
											2018-01-28 16:55:11 -08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | <!-- Good --> | 
					
						
							| 
									
										
										
										
											2019-02-27 19:09:38 +01:00
										 |  |  |  | <script crossorigin src="https://example.com/react.js"></script> | 
					
						
							|  |  |  |  | <link rel="stylesheet" href="https://example.com/style.css"> | 
					
						
							| 
									
										
										
										
											2018-01-28 16:55:11 -08:00
										 |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-29 11:19:43 -08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-29 23:29:27 +02:00
										 |  |  |  | ## 2) Do not enable Node.js Integration for Remote Content
 | 
					
						
							| 
									
										
										
										
											2018-01-28 17:25:05 -08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-29 23:29:27 +02:00
										 |  |  |  | _This recommendation is the default behavior in Electron since 5.0.0._ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | It is paramount that you do not enable Node.js integration in any renderer | 
					
						
							| 
									
										
										
										
											2018-02-01 09:58:02 -08:00
										 |  |  |  | ([`BrowserWindow`][browser-window], [`BrowserView`][browser-view], or | 
					
						
							| 
									
										
										
										
											2018-06-21 16:39:07 +02:00
										 |  |  |  | [`<webview>`][webview-tag]) that loads remote content. The goal is to limit the | 
					
						
							| 
									
										
										
										
											2018-01-29 16:01:05 -08:00
										 |  |  |  | powers you grant to remote content, thus making it dramatically more difficult | 
					
						
							|  |  |  |  | for an attacker to harm your users should they gain the ability to execute | 
					
						
							|  |  |  |  | JavaScript on your website. | 
					
						
							| 
									
										
										
										
											2018-01-29 11:19:43 -08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-29 16:01:05 -08:00
										 |  |  |  | After this, you can grant additional permissions for specific hosts. For example, | 
					
						
							| 
									
										
										
										
											2019-10-07 12:26:38 -04:00
										 |  |  |  | if you are opening a BrowserWindow pointed at `https://example.com/`, you can | 
					
						
							| 
									
										
										
										
											2018-01-29 16:01:05 -08:00
										 |  |  |  | give that website exactly the abilities it needs, but no more. | 
					
						
							| 
									
										
										
										
											2018-01-28 17:25:05 -08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | ### Why?
 | 
					
						
							| 
									
										
										
										
											2018-01-29 11:19:43 -08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-29 16:01:05 -08:00
										 |  |  |  | A cross-site-scripting (XSS) attack is more dangerous if an attacker can jump | 
					
						
							|  |  |  |  | out of the renderer process and execute code on the user's computer. | 
					
						
							|  |  |  |  | Cross-site-scripting attacks are fairly common - and while an issue, their | 
					
						
							|  |  |  |  | power is usually limited to messing with the website that they are executed on. | 
					
						
							|  |  |  |  | Disabling Node.js integration helps prevent an XSS from being escalated into a | 
					
						
							|  |  |  |  | so-called "Remote Code Execution" (RCE) attack. | 
					
						
							| 
									
										
										
										
											2018-01-28 17:25:05 -08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | ### How?
 | 
					
						
							| 
									
										
										
										
											2018-01-29 11:19:43 -08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-28 17:25:05 -08:00
										 |  |  |  | ```js | 
					
						
							|  |  |  |  | // Bad | 
					
						
							| 
									
										
										
										
											2019-04-29 23:29:27 +02:00
										 |  |  |  | const mainWindow = new BrowserWindow({ | 
					
						
							|  |  |  |  |   webPreferences: { | 
					
						
							|  |  |  |  |     nodeIntegration: true, | 
					
						
							|  |  |  |  |     nodeIntegrationInWorker: true | 
					
						
							|  |  |  |  |   } | 
					
						
							|  |  |  |  | }) | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-27 19:09:38 +01:00
										 |  |  |  | mainWindow.loadURL('https://example.com') | 
					
						
							| 
									
										
										
										
											2018-01-29 12:36:51 -08:00
										 |  |  |  | ``` | 
					
						
							| 
									
										
										
										
											2018-01-28 17:25:05 -08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-29 12:36:51 -08:00
										 |  |  |  | ```js | 
					
						
							| 
									
										
										
										
											2018-01-28 17:25:05 -08:00
										 |  |  |  | // Good | 
					
						
							|  |  |  |  | const mainWindow = new BrowserWindow({ | 
					
						
							|  |  |  |  |   webPreferences: { | 
					
						
							| 
									
										
										
										
											2019-03-28 11:38:51 +01:00
										 |  |  |  |     preload: path.join(app.getAppPath(), 'preload.js') | 
					
						
							| 
									
										
										
										
											2018-01-28 17:25:05 -08:00
										 |  |  |  |   } | 
					
						
							|  |  |  |  | }) | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-27 19:09:38 +01:00
										 |  |  |  | mainWindow.loadURL('https://example.com') | 
					
						
							| 
									
										
										
										
											2018-01-28 17:25:05 -08:00
										 |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-29 11:19:43 -08:00
										 |  |  |  | ```html | 
					
						
							|  |  |  |  | <!-- Bad --> | 
					
						
							|  |  |  |  | <webview nodeIntegration src="page.html"></webview> | 
					
						
							| 
									
										
										
										
											2018-01-28 17:25:05 -08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-29 11:19:43 -08:00
										 |  |  |  | <!-- Good --> | 
					
						
							|  |  |  |  | <webview src="page.html"></webview> | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-29 16:01:05 -08:00
										 |  |  |  | When disabling Node.js integration, you can still expose APIs to your website that | 
					
						
							| 
									
										
										
										
											2018-01-29 11:19:43 -08:00
										 |  |  |  | do consume Node.js modules or features. Preload scripts continue to have access | 
					
						
							|  |  |  |  | to `require` and other Node.js features, allowing developers to expose a custom | 
					
						
							|  |  |  |  | API to remotely loaded content. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | In the following example preload script, the later loaded website will have | 
					
						
							|  |  |  |  | access to a `window.readConfig()` method, but no Node.js features. | 
					
						
							| 
									
										
										
										
											2018-01-28 17:25:05 -08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | ```js | 
					
						
							|  |  |  |  | const { readFileSync } = require('fs') | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | window.readConfig = function () { | 
					
						
							|  |  |  |  |   const data = readFileSync('./config.json') | 
					
						
							| 
									
										
										
										
											2018-01-29 12:36:51 -08:00
										 |  |  |  |   return data | 
					
						
							| 
									
										
										
										
											2018-01-28 17:25:05 -08:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-29 11:19:21 -08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-01 09:58:02 -08:00
										 |  |  |  | ## 3) Enable Context Isolation for Remote Content
 | 
					
						
							| 
									
										
										
										
											2018-01-29 11:01:22 -08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-29 11:19:21 -08:00
										 |  |  |  | Context isolation is an Electron feature that allows developers to run code | 
					
						
							|  |  |  |  | in preload scripts and in Electron APIs in a dedicated JavaScript context. In | 
					
						
							|  |  |  |  | practice, that means that global objects like `Array.prototype.push` or | 
					
						
							|  |  |  |  | `JSON.parse` cannot be modified by scripts running in the renderer process. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | Electron uses the same technology as Chromium's [Content Scripts](https://developer.chrome.com/extensions/content_scripts#execution-environment) | 
					
						
							|  |  |  |  | to enable this behavior. | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-27 19:09:38 +01:00
										 |  |  |  | Even when you use `nodeIntegration: false` to enforce strong isolation and | 
					
						
							|  |  |  |  | prevent the use of Node primitives, `contextIsolation` must also be used. | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-29 11:19:21 -08:00
										 |  |  |  | ### Why?
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-03 17:11:02 +01:00
										 |  |  |  | Context isolation allows each of the scripts running in the renderer to make | 
					
						
							| 
									
										
										
										
											2018-01-29 11:19:21 -08:00
										 |  |  |  | changes to its JavaScript environment without worrying about conflicting with | 
					
						
							|  |  |  |  | the scripts in the Electron API or the preload script. | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-29 16:01:05 -08:00
										 |  |  |  | While still an experimental Electron feature, context isolation adds an | 
					
						
							|  |  |  |  | additional layer of security. It creates a new JavaScript world for Electron | 
					
						
							| 
									
										
										
										
											2019-02-27 19:09:38 +01:00
										 |  |  |  | APIs and preload scripts, which mitigates so-called "Prototype Pollution" attacks. | 
					
						
							| 
									
										
										
										
											2018-01-29 16:01:05 -08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | At the same time, preload scripts still have access to the  `document` and | 
					
						
							|  |  |  |  | `window` objects. In other words, you're getting a decent return on a likely | 
					
						
							|  |  |  |  | very small investment. | 
					
						
							| 
									
										
										
										
											2018-01-29 11:19:21 -08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | ### How?
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ```js | 
					
						
							|  |  |  |  | // Main process | 
					
						
							|  |  |  |  | const mainWindow = new BrowserWindow({ | 
					
						
							|  |  |  |  |   webPreferences: { | 
					
						
							|  |  |  |  |     contextIsolation: true, | 
					
						
							| 
									
										
										
										
											2019-03-28 11:38:51 +01:00
										 |  |  |  |     preload: path.join(app.getAppPath(), 'preload.js') | 
					
						
							| 
									
										
										
										
											2018-01-29 11:19:21 -08:00
										 |  |  |  |   } | 
					
						
							|  |  |  |  | }) | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ```js | 
					
						
							|  |  |  |  | // Preload script | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // Set a variable in the page before it loads | 
					
						
							|  |  |  |  | webFrame.executeJavaScript('window.foo = "foo";') | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // The loaded page will not be able to access this, it is only available | 
					
						
							|  |  |  |  | // in this context | 
					
						
							|  |  |  |  | window.bar = 'bar' | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | document.addEventListener('DOMContentLoaded', () => { | 
					
						
							|  |  |  |  |   // Will log out 'undefined' since window.foo is only available in the main | 
					
						
							|  |  |  |  |   // context | 
					
						
							|  |  |  |  |   console.log(window.foo) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   // Will log out 'bar' since window.bar is available in this context | 
					
						
							|  |  |  |  |   console.log(window.bar) | 
					
						
							|  |  |  |  | }) | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-29 11:19:43 -08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-01 09:58:02 -08:00
										 |  |  |  | ## 4) Handle Session Permission Requests From Remote Content
 | 
					
						
							| 
									
										
										
										
											2018-01-29 11:01:22 -08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | You may have seen permission requests while using Chrome: They pop up whenever | 
					
						
							|  |  |  |  | the website attempts to use a feature that the user has to manually approve ( | 
					
						
							|  |  |  |  | like notifications). | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | The API is based on the [Chromium permissions API](https://developer.chrome.com/extensions/permissions) | 
					
						
							|  |  |  |  | and implements the same types of permissions. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ### Why?
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | By default, Electron will automatically approve all permission requests unless | 
					
						
							|  |  |  |  | the developer has manually configured a custom handler. While a solid default, | 
					
						
							|  |  |  |  | security-conscious developers might want to assume the very opposite. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ### How?
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ```js | 
					
						
							|  |  |  |  | const { session } = require('electron') | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | session | 
					
						
							|  |  |  |  |   .fromPartition('some-partition') | 
					
						
							|  |  |  |  |   .setPermissionRequestHandler((webContents, permission, callback) => { | 
					
						
							|  |  |  |  |     const url = webContents.getURL() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     if (permission === 'notifications') { | 
					
						
							|  |  |  |  |       // Approves the permissions request | 
					
						
							|  |  |  |  |       callback(true) | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-06 19:43:58 +01:00
										 |  |  |  |     // Verify URL | 
					
						
							| 
									
										
										
										
											2019-02-27 19:09:38 +01:00
										 |  |  |  |     if (!url.startsWith('https://example.com/')) { | 
					
						
							| 
									
										
										
										
											2018-01-29 11:01:22 -08:00
										 |  |  |  |       // Denies the permissions request | 
					
						
							|  |  |  |  |       return callback(false) | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   }) | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-01 09:58:02 -08:00
										 |  |  |  | ## 5) Do Not Disable WebSecurity
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | _Recommendation is Electron's default_ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | You may have already guessed that disabling the `webSecurity` property on a | 
					
						
							|  |  |  |  | renderer process ([`BrowserWindow`][browser-window], | 
					
						
							| 
									
										
										
										
											2018-06-21 16:39:07 +02:00
										 |  |  |  | [`BrowserView`][browser-view], or [`<webview>`][webview-tag]) disables crucial | 
					
						
							| 
									
										
										
										
											2018-02-01 09:58:02 -08:00
										 |  |  |  | security features. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | Do not disable `webSecurity` in production applications. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ### Why?
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | Disabling `webSecurity` will disable the same-origin policy and set | 
					
						
							|  |  |  |  | `allowRunningInsecureContent` property to `true`. In other words, it allows | 
					
						
							|  |  |  |  | the execution of insecure code from different domains. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ### How?
 | 
					
						
							|  |  |  |  | ```js | 
					
						
							|  |  |  |  | // Bad | 
					
						
							|  |  |  |  | const mainWindow = new BrowserWindow({ | 
					
						
							|  |  |  |  |   webPreferences: { | 
					
						
							|  |  |  |  |     webSecurity: false | 
					
						
							|  |  |  |  |   } | 
					
						
							|  |  |  |  | }) | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ```js | 
					
						
							|  |  |  |  | // Good | 
					
						
							|  |  |  |  | const mainWindow = new BrowserWindow() | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ```html | 
					
						
							|  |  |  |  | <!-- Bad --> | 
					
						
							|  |  |  |  | <webview disablewebsecurity src="page.html"></webview> | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | <!-- Good --> | 
					
						
							|  |  |  |  | <webview src="page.html"></webview> | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ## 6) Define a Content Security Policy
 | 
					
						
							| 
									
										
										
										
											2018-01-29 11:02:30 -08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | A Content Security Policy (CSP) is an additional layer of protection against | 
					
						
							| 
									
										
										
										
											2018-01-29 16:01:05 -08:00
										 |  |  |  | cross-site-scripting attacks and data injection attacks. We recommend that they | 
					
						
							|  |  |  |  | be enabled by any website you load inside Electron. | 
					
						
							| 
									
										
										
										
											2018-01-29 11:02:30 -08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | ### Why?
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | CSP allows the server serving content to restrict and control the resources | 
					
						
							| 
									
										
										
										
											2019-02-27 19:09:38 +01:00
										 |  |  |  | Electron can load for that given web page. `https://example.com` should | 
					
						
							| 
									
										
										
										
											2018-01-29 16:01:05 -08:00
										 |  |  |  | be allowed to load scripts from the origins you defined while scripts from | 
					
						
							| 
									
										
										
										
											2018-01-29 11:02:30 -08:00
										 |  |  |  | `https://evil.attacker.com` should not be allowed to run. Defining a CSP is an | 
					
						
							| 
									
										
										
										
											2018-06-19 17:36:37 -07:00
										 |  |  |  | easy way to improve your application's security. | 
					
						
							| 
									
										
										
										
											2018-01-29 11:02:30 -08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | The following CSP will allow Electron to execute scripts from the current | 
					
						
							| 
									
										
										
										
											2019-02-27 19:09:38 +01:00
										 |  |  |  | website and from `apis.example.com`. | 
					
						
							| 
									
										
										
										
											2018-01-29 11:02:30 -08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-30 13:11:56 -07:00
										 |  |  |  | ```plaintext | 
					
						
							| 
									
										
										
										
											2018-01-29 11:02:30 -08:00
										 |  |  |  | // Bad | 
					
						
							|  |  |  |  | Content-Security-Policy: '*' | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // Good | 
					
						
							| 
									
										
										
										
											2019-02-27 19:09:38 +01:00
										 |  |  |  | Content-Security-Policy: script-src 'self' https://apis.example.com | 
					
						
							| 
									
										
										
										
											2018-01-29 11:02:30 -08:00
										 |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-19 17:36:37 -07:00
										 |  |  |  | ### CSP HTTP Header
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | Electron respects the [`Content-Security-Policy` HTTP header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy) | 
					
						
							| 
									
										
										
										
											2018-07-16 13:32:42 -07:00
										 |  |  |  | which can be set using Electron's | 
					
						
							| 
									
										
										
										
											2018-06-19 17:36:37 -07:00
										 |  |  |  | [`webRequest.onHeadersReceived`](../api/web-request.md#webrequestonheadersreceivedfilter-listener) | 
					
						
							|  |  |  |  | handler: | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ```javascript | 
					
						
							| 
									
										
										
										
											2018-09-14 02:10:51 +10:00
										 |  |  |  | const { session } = require('electron') | 
					
						
							| 
									
										
										
										
											2018-06-19 17:36:37 -07:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | session.defaultSession.webRequest.onHeadersReceived((details, callback) => { | 
					
						
							| 
									
										
										
										
											2018-10-23 23:38:48 +09:00
										 |  |  |  |   callback({ | 
					
						
							|  |  |  |  |     responseHeaders: { | 
					
						
							|  |  |  |  |       ...details.responseHeaders, | 
					
						
							|  |  |  |  |       'Content-Security-Policy': ['default-src \'none\''] | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   }) | 
					
						
							| 
									
										
										
										
											2018-06-19 17:36:37 -07:00
										 |  |  |  | }) | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ### CSP Meta Tag
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 03:58:18 -05:00
										 |  |  |  | CSP's preferred delivery mechanism is an HTTP header, however it is not possible | 
					
						
							|  |  |  |  | to use this method when loading a resource using the `file://` protocol. It can | 
					
						
							|  |  |  |  | be useful in some cases, such as using the `file://` protocol, to set a policy | 
					
						
							|  |  |  |  | on a page directly in the markup using a `<meta>` tag: | 
					
						
							| 
									
										
										
										
											2018-06-19 17:36:37 -07:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | ```html | 
					
						
							|  |  |  |  | <meta http-equiv="Content-Security-Policy" content="default-src 'none'"> | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-29 11:02:30 -08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-12 11:13:48 -05:00
										 |  |  |  | ## 7) Do Not Set `allowRunningInsecureContent` to `true`
 | 
					
						
							| 
									
										
										
										
											2018-01-29 11:03:06 -08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-29 12:34:46 -08:00
										 |  |  |  | _Recommendation is Electron's default_ | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-27 16:15:29 -07:00
										 |  |  |  | By default, Electron will not allow websites loaded over `HTTPS` to load and | 
					
						
							| 
									
										
										
										
											2018-01-29 11:03:06 -08:00
										 |  |  |  | execute scripts, CSS, or plugins from insecure sources (`HTTP`). Setting the | 
					
						
							|  |  |  |  | property `allowRunningInsecureContent` to `true` disables that protection. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | Loading the initial HTML of a website over `HTTPS` and attempting to load | 
					
						
							|  |  |  |  | subsequent resources via `HTTP` is also known as "mixed content". | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ### Why?
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-08 00:16:09 -05:00
										 |  |  |  | Loading content over `HTTPS` assures the authenticity and integrity | 
					
						
							| 
									
										
										
										
											2018-01-29 16:01:05 -08:00
										 |  |  |  | of the loaded resources while encrypting the traffic itself. See the section on | 
					
						
							| 
									
										
										
										
											2018-05-02 10:33:07 -05:00
										 |  |  |  | [only displaying secure content](#1-only-load-secure-content) for more details. | 
					
						
							| 
									
										
										
										
											2018-01-29 11:03:06 -08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | ### How?
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ```js | 
					
						
							|  |  |  |  | // Bad | 
					
						
							|  |  |  |  | const mainWindow = new BrowserWindow({ | 
					
						
							|  |  |  |  |   webPreferences: { | 
					
						
							|  |  |  |  |     allowRunningInsecureContent: true | 
					
						
							|  |  |  |  |   } | 
					
						
							|  |  |  |  | }) | 
					
						
							| 
									
										
										
										
											2018-01-29 12:36:51 -08:00
										 |  |  |  | ``` | 
					
						
							| 
									
										
										
										
											2018-01-29 11:03:06 -08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-29 12:36:51 -08:00
										 |  |  |  | ```js | 
					
						
							| 
									
										
										
										
											2018-01-29 11:03:06 -08:00
										 |  |  |  | // Good | 
					
						
							|  |  |  |  | const mainWindow = new BrowserWindow({}) | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-29 11:03:27 -08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-12 11:13:48 -05:00
										 |  |  |  | ## 8) Do Not Enable Experimental Features
 | 
					
						
							| 
									
										
										
										
											2018-01-29 11:03:27 -08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-29 12:34:46 -08:00
										 |  |  |  | _Recommendation is Electron's default_ | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-29 11:03:27 -08:00
										 |  |  |  | Advanced users of Electron can enable experimental Chromium features using the | 
					
						
							| 
									
										
										
										
											2018-07-16 13:32:42 -07:00
										 |  |  |  | `experimentalFeatures` property. | 
					
						
							| 
									
										
										
										
											2018-01-29 11:03:27 -08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | ### Why?
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | Experimental features are, as the name suggests, experimental and have not been | 
					
						
							| 
									
										
										
										
											2018-02-13 00:18:27 -05:00
										 |  |  |  | enabled for all Chromium users. Furthermore, their impact on Electron as a whole | 
					
						
							| 
									
										
										
										
											2018-01-29 11:03:27 -08:00
										 |  |  |  | has likely not been tested. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | Legitimate use cases exist, but unless you know what you are doing, you should | 
					
						
							|  |  |  |  | not enable this property. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ### How?
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ```js | 
					
						
							|  |  |  |  | // Bad | 
					
						
							|  |  |  |  | const mainWindow = new BrowserWindow({ | 
					
						
							|  |  |  |  |   webPreferences: { | 
					
						
							|  |  |  |  |     experimentalFeatures: true | 
					
						
							|  |  |  |  |   } | 
					
						
							|  |  |  |  | }) | 
					
						
							| 
									
										
										
										
											2018-01-29 12:36:51 -08:00
										 |  |  |  | ``` | 
					
						
							| 
									
										
										
										
											2018-01-29 11:03:27 -08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-29 12:36:51 -08:00
										 |  |  |  | ```js | 
					
						
							| 
									
										
										
										
											2018-01-29 11:03:27 -08:00
										 |  |  |  | // Good | 
					
						
							|  |  |  |  | const mainWindow = new BrowserWindow({}) | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-29 11:03:38 -08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-12 11:13:48 -05:00
										 |  |  |  | ## 9) Do Not Use `enableBlinkFeatures`
 | 
					
						
							| 
									
										
										
										
											2018-01-29 12:34:46 -08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | _Recommendation is Electron's default_ | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-29 16:01:05 -08:00
										 |  |  |  | Blink is the name of the rendering engine behind Chromium. As with | 
					
						
							| 
									
										
										
										
											2018-05-23 14:01:34 -07:00
										 |  |  |  | `experimentalFeatures`, the `enableBlinkFeatures` property allows developers to | 
					
						
							| 
									
										
										
										
											2018-01-29 11:03:38 -08:00
										 |  |  |  | enable features that have been disabled by default. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ### Why?
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | Generally speaking, there are likely good reasons if a feature was not enabled | 
					
						
							|  |  |  |  | by default. Legitimate use cases for enabling specific features exist. As a | 
					
						
							|  |  |  |  | developer, you should know exactly why you need to enable a feature, what the | 
					
						
							|  |  |  |  | ramifications are, and how it impacts the security of your application. Under | 
					
						
							|  |  |  |  | no circumstances should you enable features speculatively. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ### How?
 | 
					
						
							|  |  |  |  | ```js | 
					
						
							|  |  |  |  | // Bad | 
					
						
							|  |  |  |  | const mainWindow = new BrowserWindow({ | 
					
						
							|  |  |  |  |   webPreferences: { | 
					
						
							| 
									
										
										
										
											2019-09-03 00:02:22 -07:00
										 |  |  |  |     enableBlinkFeatures: 'ExecCommandInJavaScript' | 
					
						
							| 
									
										
										
										
											2018-01-29 11:03:38 -08:00
										 |  |  |  |   } | 
					
						
							|  |  |  |  | }) | 
					
						
							| 
									
										
										
										
											2018-01-29 12:36:51 -08:00
										 |  |  |  | ``` | 
					
						
							| 
									
										
										
										
											2018-01-29 11:03:38 -08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-29 12:36:51 -08:00
										 |  |  |  | ```js | 
					
						
							| 
									
										
										
										
											2018-01-29 11:03:38 -08:00
										 |  |  |  | // Good | 
					
						
							|  |  |  |  | const mainWindow = new BrowserWindow() | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-12 11:13:48 -05:00
										 |  |  |  | ## 10) Do Not Use `allowpopups`
 | 
					
						
							| 
									
										
										
										
											2018-01-29 11:04:02 -08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-29 12:34:46 -08:00
										 |  |  |  | _Recommendation is Electron's default_ | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-21 16:39:07 +02:00
										 |  |  |  | If you are using [`<webview>`][webview-tag], you might need the pages and scripts | 
					
						
							| 
									
										
										
										
											2018-01-29 12:34:46 -08:00
										 |  |  |  | loaded in your `<webview>` tag to open new windows. The `allowpopups` attribute | 
					
						
							| 
									
										
										
										
											2018-02-19 18:25:02 -06:00
										 |  |  |  | enables them to create new [`BrowserWindows`][browser-window] using the | 
					
						
							| 
									
										
										
										
											2018-06-21 16:39:07 +02:00
										 |  |  |  | `window.open()` method. `<webview>` tags are otherwise not allowed to create new | 
					
						
							| 
									
										
										
										
											2018-01-29 12:34:46 -08:00
										 |  |  |  | windows. | 
					
						
							| 
									
										
										
										
											2018-01-29 11:04:02 -08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | ### Why?
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | If you do not need popups, you are better off not allowing the creation of | 
					
						
							| 
									
										
										
										
											2018-02-19 18:25:02 -06:00
										 |  |  |  | new [`BrowserWindows`][browser-window] by default. This follows the principle | 
					
						
							| 
									
										
										
										
											2018-01-29 16:01:05 -08:00
										 |  |  |  | of minimally required access: Don't let a website create new popups unless | 
					
						
							|  |  |  |  | you know it needs that feature. | 
					
						
							| 
									
										
										
										
											2018-01-29 11:04:02 -08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | ### How?
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ```html | 
					
						
							|  |  |  |  | <!-- Bad --> | 
					
						
							|  |  |  |  | <webview allowpopups src="page.html"></webview> | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | <!-- Good --> | 
					
						
							|  |  |  |  | <webview src="page.html"></webview> | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-12 11:13:48 -05:00
										 |  |  |  | ## 11) Verify WebView Options Before Creation
 | 
					
						
							| 
									
										
										
										
											2018-01-29 11:19:43 -08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-28 18:19:49 -08:00
										 |  |  |  | A WebView created in a renderer process that does not have Node.js integration | 
					
						
							|  |  |  |  | enabled will not be able to enable integration itself. However, a WebView will | 
					
						
							|  |  |  |  | always create an independent renderer process with its own `webPreferences`. | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-21 16:39:07 +02:00
										 |  |  |  | It is a good idea to control the creation of new [`<webview>`][webview-tag] tags | 
					
						
							|  |  |  |  | from the main process and to verify that their webPreferences do not disable | 
					
						
							| 
									
										
										
										
											2018-01-29 12:34:46 -08:00
										 |  |  |  | security features. | 
					
						
							| 
									
										
										
										
											2018-01-28 18:19:49 -08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | ### Why?
 | 
					
						
							| 
									
										
										
										
											2018-01-29 11:19:43 -08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-21 16:39:07 +02:00
										 |  |  |  | Since `<webview>` live in the DOM, they can be created by a script running on your | 
					
						
							| 
									
										
										
										
											2018-01-29 16:01:05 -08:00
										 |  |  |  | website even if Node.js integration is otherwise disabled. | 
					
						
							| 
									
										
										
										
											2018-01-28 18:19:49 -08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | Electron enables developers to disable various security features that control | 
					
						
							| 
									
										
										
										
											2018-01-29 11:19:43 -08:00
										 |  |  |  | a renderer process. In most cases, developers do not need to disable any of | 
					
						
							|  |  |  |  | those features - and you should therefore not allow different configurations | 
					
						
							| 
									
										
										
										
											2018-06-21 16:39:07 +02:00
										 |  |  |  | for newly created [`<webview>`][webview-tag] tags. | 
					
						
							| 
									
										
										
										
											2018-01-28 18:19:49 -08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | ### How?
 | 
					
						
							| 
									
										
										
										
											2018-01-29 11:19:43 -08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-21 16:39:07 +02:00
										 |  |  |  | Before a [`<webview>`][webview-tag] tag is attached, Electron will fire the | 
					
						
							| 
									
										
										
										
											2018-01-28 18:19:49 -08:00
										 |  |  |  | `will-attach-webview` event on the hosting `webContents`. Use the event to | 
					
						
							| 
									
										
										
										
											2018-07-31 11:40:26 -07:00
										 |  |  |  | prevent the creation of `webViews` with possibly insecure options. | 
					
						
							| 
									
										
										
										
											2018-01-28 18:19:49 -08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | ```js | 
					
						
							|  |  |  |  | app.on('web-contents-created', (event, contents) => { | 
					
						
							|  |  |  |  |   contents.on('will-attach-webview', (event, webPreferences, params) => { | 
					
						
							|  |  |  |  |     // Strip away preload scripts if unused or verify their location is legitimate | 
					
						
							|  |  |  |  |     delete webPreferences.preload | 
					
						
							|  |  |  |  |     delete webPreferences.preloadURL | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-29 16:01:05 -08:00
										 |  |  |  |     // Disable Node.js integration | 
					
						
							| 
									
										
										
										
											2018-01-28 18:19:49 -08:00
										 |  |  |  |     webPreferences.nodeIntegration = false | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     // Verify URL being loaded | 
					
						
							| 
									
										
										
										
											2019-02-27 19:09:38 +01:00
										 |  |  |  |     if (!params.src.startsWith('https://example.com/')) { | 
					
						
							| 
									
										
										
										
											2018-01-28 18:19:49 -08:00
										 |  |  |  |       event.preventDefault() | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   }) | 
					
						
							|  |  |  |  | }) | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-10 17:41:16 +09:00
										 |  |  |  | Again, this list merely minimizes the risk, it does not remove it. If your goal | 
					
						
							|  |  |  |  | is to display a website, a browser will be a more secure option. | 
					
						
							| 
									
										
										
										
											2018-01-29 12:34:46 -08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-12 11:13:48 -05:00
										 |  |  |  | ## 12) Disable or limit navigation
 | 
					
						
							| 
									
										
										
										
											2018-07-31 11:40:26 -07:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | If your app has no need to navigate or only needs to navigate to known pages, | 
					
						
							|  |  |  |  | it is a good idea to limit navigation outright to that known scope, disallowing | 
					
						
							|  |  |  |  | any other kinds of navigation. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ### Why?
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | Navigation is a common attack vector. If an attacker can convince your app to | 
					
						
							|  |  |  |  | navigate away from its current page, they can possibly force your app to open | 
					
						
							|  |  |  |  | web sites on the Internet. Even if your `webContents` are configured to be more | 
					
						
							|  |  |  |  | secure (like having `nodeIntegration` disabled or `contextIsolation` enabled), | 
					
						
							|  |  |  |  | getting your app to open a random web site will make the work of exploiting your | 
					
						
							|  |  |  |  | app a lot easier. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | A common attack pattern is that the attacker convinces your app's users to | 
					
						
							|  |  |  |  | interact with the app in such a way that it navigates to one of the attacker's | 
					
						
							|  |  |  |  | pages. This is usually done via links, plugins, or other user-generated content. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ### How?
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | If your app has no need for navigation, you can call `event.preventDefault()` | 
					
						
							|  |  |  |  | in a [`will-navigate`][will-navigate] handler. If you know which pages your app | 
					
						
							|  |  |  |  | might navigate to, check the URL in the event handler and only let navigation | 
					
						
							|  |  |  |  | occur if it matches the URLs you're expecting. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | We recommend that you use Node's parser for URLs. Simple string comparisons can | 
					
						
							| 
									
										
										
										
											2019-02-27 19:09:38 +01:00
										 |  |  |  | sometimes be fooled - a `startsWith('https://example.com')` test would let | 
					
						
							|  |  |  |  | `https://example.com.attacker.com` through. | 
					
						
							| 
									
										
										
										
											2018-07-31 11:40:26 -07:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | ```js | 
					
						
							| 
									
										
										
										
											2018-08-18 22:41:55 -04:00
										 |  |  |  | const URL = require('url').URL | 
					
						
							| 
									
										
										
										
											2018-07-31 11:40:26 -07:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | app.on('web-contents-created', (event, contents) => { | 
					
						
							|  |  |  |  |   contents.on('will-navigate', (event, navigationUrl) => { | 
					
						
							|  |  |  |  |     const parsedUrl = new URL(navigationUrl) | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-27 19:09:38 +01:00
										 |  |  |  |     if (parsedUrl.origin !== 'https://example.com') { | 
					
						
							| 
									
										
										
										
											2018-07-31 11:40:26 -07:00
										 |  |  |  |       event.preventDefault() | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   }) | 
					
						
							|  |  |  |  | }) | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-12 11:13:48 -05:00
										 |  |  |  | ## 13) Disable or limit creation of new windows
 | 
					
						
							| 
									
										
										
										
											2018-07-31 11:40:26 -07:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | If you have a known set of windows, it's a good idea to limit the creation of | 
					
						
							|  |  |  |  | additional windows in your app. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ### Why?
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | Much like navigation, the creation of new `webContents` is a common attack | 
					
						
							|  |  |  |  | vector. Attackers attempt to convince your app to create new windows, frames, | 
					
						
							|  |  |  |  | or other renderer processes with more privileges than they had before; or | 
					
						
							|  |  |  |  | with pages opened that they couldn't open before. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | If you have no need to create windows in addition to the ones you know you'll | 
					
						
							|  |  |  |  | need to create, disabling the creation buys you a little bit of extra | 
					
						
							|  |  |  |  | security at no cost. This is commonly the case for apps that open one | 
					
						
							|  |  |  |  | `BrowserWindow` and do not need to open an arbitrary number of additional | 
					
						
							|  |  |  |  | windows at runtime. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ### How?
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | [`webContents`][web-contents] will emit the [`new-window`][new-window] event | 
					
						
							|  |  |  |  | before creating new windows. That event will be passed, amongst other | 
					
						
							|  |  |  |  | parameters, the `url` the window was requested to open and the options used to | 
					
						
							|  |  |  |  | create it. We recommend that you use the event to scrutinize the creation of | 
					
						
							|  |  |  |  | windows, limiting it to only what you need. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ```js | 
					
						
							|  |  |  |  | const { shell } = require('electron') | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | app.on('web-contents-created', (event, contents) => { | 
					
						
							| 
									
										
										
										
											2019-05-03 13:53:45 -07:00
										 |  |  |  |   contents.on('new-window', async (event, navigationUrl) => { | 
					
						
							| 
									
										
										
										
											2018-07-31 11:40:26 -07:00
										 |  |  |  |     // In this example, we'll ask the operating system | 
					
						
							|  |  |  |  |     // to open this event's url in the default browser. | 
					
						
							|  |  |  |  |     event.preventDefault() | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-03 13:53:45 -07:00
										 |  |  |  |     await shell.openExternal(navigationUrl) | 
					
						
							| 
									
										
										
										
											2018-07-31 11:40:26 -07:00
										 |  |  |  |   }) | 
					
						
							|  |  |  |  | }) | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-27 19:09:38 +01:00
										 |  |  |  | ## 14) Do not use `openExternal` with untrusted content
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | Shell's [`openExternal`][open-external] allows opening a given protocol URI with | 
					
						
							|  |  |  |  | the desktop's native utilities. On macOS, for instance, this function is similar | 
					
						
							|  |  |  |  | to the `open` terminal command utility and will open the specific application | 
					
						
							|  |  |  |  | based on the URI and filetype association. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ### Why?
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | Improper use of [`openExternal`][open-external] can be leveraged to compromise | 
					
						
							|  |  |  |  | the user's host. When openExternal is used with untrusted content, it can be | 
					
						
							|  |  |  |  | leveraged to execute arbitrary commands. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ### How?
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ```js | 
					
						
							|  |  |  |  | //  Bad | 
					
						
							|  |  |  |  | const { shell } = require('electron') | 
					
						
							|  |  |  |  | shell.openExternal(USER_CONTROLLED_DATA_HERE) | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | ```js | 
					
						
							|  |  |  |  | //  Good | 
					
						
							|  |  |  |  | const { shell } = require('electron') | 
					
						
							|  |  |  |  | shell.openExternal('https://example.com/index.html') | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-05 20:41:05 +02:00
										 |  |  |  | ## 15) Disable the `remote` module
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | The `remote` module provides a way for the renderer processes to | 
					
						
							|  |  |  |  | access APIs normally only available in the main process. Using it, a | 
					
						
							|  |  |  |  | renderer can invoke methods of a main process object without explicitly sending | 
					
						
							|  |  |  |  | inter-process messages. If your desktop application does not run untrusted | 
					
						
							|  |  |  |  | content, this can be a useful way to have your renderer processes access and | 
					
						
							|  |  |  |  | work with modules that are only available to the main process, such as | 
					
						
							|  |  |  |  | GUI-related modules (dialogs, menus, etc.). | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | However, if your app can run untrusted content and even if you | 
					
						
							|  |  |  |  | [sandbox][sandbox] your renderer processes accordingly, the `remote` module | 
					
						
							|  |  |  |  | makes it easy for malicious code to escape the sandbox and have access to | 
					
						
							|  |  |  |  | system resources via the higher privileges of the main process. Therefore, | 
					
						
							|  |  |  |  | it should be disabled in such circumstances. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ### Why?
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | `remote` uses an internal IPC channel to communicate with the main process. | 
					
						
							|  |  |  |  | "Prototype pollution" attacks can grant malicious code access to the internal | 
					
						
							|  |  |  |  | IPC channel, which can then be used to escape the sandbox by mimicking `remote` | 
					
						
							|  |  |  |  | IPC messages and getting access to main process modules running with higher | 
					
						
							|  |  |  |  | privileges. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | Additionally, it's possible for preload scripts to accidentally leak modules to a | 
					
						
							|  |  |  |  | sandboxed renderer. Leaking `remote` arms malicious code with a multitude | 
					
						
							|  |  |  |  | of main process modules with which to perform an attack. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | Disabling the `remote` module eliminates these attack vectors. Enabling | 
					
						
							|  |  |  |  | context isolation also prevents the "prototype pollution" attacks from | 
					
						
							|  |  |  |  | succeeding. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ### How?
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ```js | 
					
						
							|  |  |  |  | // Bad if the renderer can run untrusted content | 
					
						
							|  |  |  |  | const mainWindow = new BrowserWindow({}) | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ```js | 
					
						
							|  |  |  |  | // Good | 
					
						
							|  |  |  |  | const mainWindow = new BrowserWindow({ | 
					
						
							|  |  |  |  |   webPreferences: { | 
					
						
							|  |  |  |  |     enableRemoteModule: false | 
					
						
							|  |  |  |  |   } | 
					
						
							|  |  |  |  | }) | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ```html | 
					
						
							|  |  |  |  | <!-- Bad if the renderer can run untrusted content  --> | 
					
						
							|  |  |  |  | <webview src="page.html"></webview> | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | <!-- Good --> | 
					
						
							|  |  |  |  | <webview enableremotemodule="false" src="page.html"></webview> | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ## 16) Filter the `remote` module
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | If you cannot disable the `remote` module, you should filter the globals, | 
					
						
							|  |  |  |  | Node, and Electron modules (so-called built-ins) accessible via `remote` | 
					
						
							|  |  |  |  | that your application does not require. This can be done by blocking | 
					
						
							|  |  |  |  | certain modules entirely and by replacing others with proxies that | 
					
						
							|  |  |  |  | expose only the functionality that your app needs. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ### Why?
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | Due to the system access privileges of the main process, functionality | 
					
						
							|  |  |  |  | provided by the main process modules may be dangerous in the hands of | 
					
						
							|  |  |  |  | malicious code running in a compromised renderer process. By limiting | 
					
						
							|  |  |  |  | the set of accessible modules to the minimum that your app needs and | 
					
						
							|  |  |  |  | filtering out the others, you reduce the toolset that malicious code | 
					
						
							|  |  |  |  | can use to attack the system. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | Note that the safest option is to | 
					
						
							|  |  |  |  | [fully disable the remote module](#15-disable-the-remote-module). If | 
					
						
							|  |  |  |  | you choose to filter access rather than completely disable the module, | 
					
						
							|  |  |  |  | you must be very careful to ensure that no escalation of privilege is | 
					
						
							|  |  |  |  | possible through the modules you allow past the filter. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ### How?
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ```js | 
					
						
							|  |  |  |  | const readOnlyFsProxy = require(/* ... */) // exposes only file read functionality | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | const allowedModules = new Set(['crypto']) | 
					
						
							|  |  |  |  | const proxiedModules = new Map(['fs', readOnlyFsProxy]) | 
					
						
							|  |  |  |  | const allowedElectronModules = new Set(['shell']) | 
					
						
							|  |  |  |  | const allowedGlobals = new Set() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | app.on('remote-require', (event, webContents, moduleName) => { | 
					
						
							|  |  |  |  |   if (proxiedModules.has(moduleName)) { | 
					
						
							|  |  |  |  |     event.returnValue = proxiedModules.get(moduleName) | 
					
						
							|  |  |  |  |   } | 
					
						
							|  |  |  |  |   if (!allowedModules.has(moduleName)) { | 
					
						
							|  |  |  |  |     event.preventDefault() | 
					
						
							|  |  |  |  |   } | 
					
						
							|  |  |  |  | }) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | app.on('remote-get-builtin', (event, webContents, moduleName) => { | 
					
						
							|  |  |  |  |   if (!allowedElectronModules.has(moduleName)) { | 
					
						
							|  |  |  |  |     event.preventDefault() | 
					
						
							|  |  |  |  |   } | 
					
						
							|  |  |  |  | }) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | app.on('remote-get-global', (event, webContents, globalName) => { | 
					
						
							|  |  |  |  |   if (!allowedGlobals.has(globalName)) { | 
					
						
							|  |  |  |  |     event.preventDefault() | 
					
						
							|  |  |  |  |   } | 
					
						
							|  |  |  |  | }) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | app.on('remote-get-current-window', (event, webContents) => { | 
					
						
							|  |  |  |  |   event.preventDefault() | 
					
						
							|  |  |  |  | }) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | app.on('remote-get-current-web-contents', (event, webContents) => { | 
					
						
							|  |  |  |  |   event.preventDefault() | 
					
						
							|  |  |  |  | }) | 
					
						
							|  |  |  |  | ``` | 
					
						
							| 
									
										
										
										
											2019-02-27 19:09:38 +01:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-13 21:12:14 -04:00
										 |  |  |  | ## 17) Use a current version of Electron
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | You should strive for always using the latest available version of Electron. | 
					
						
							|  |  |  |  | Whenever a new major version is released, you should attempt to update your | 
					
						
							|  |  |  |  | app as quickly as possible. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ### Why?
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | An application built with an older version of Electron, Chromium, and Node.js | 
					
						
							|  |  |  |  | is an easier target than an application that is using more recent versions of | 
					
						
							|  |  |  |  | those components. Generally speaking, security issues and exploits for older | 
					
						
							|  |  |  |  | versions of Chromium and Node.js are more widely available. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | Both Chromium and Node.js are impressive feats of engineering built by | 
					
						
							|  |  |  |  | thousands of talented developers. Given their popularity, their security is | 
					
						
							|  |  |  |  | carefully tested and analyzed by equally skilled security researchers. Many of | 
					
						
							|  |  |  |  | those researchers [disclose vulnerabilities responsibly][responsible-disclosure], | 
					
						
							|  |  |  |  | which generally means that researchers will give Chromium and Node.js some time | 
					
						
							|  |  |  |  | to fix issues before publishing them. Your application will be more secure if | 
					
						
							|  |  |  |  | it is running a recent version of Electron (and thus, Chromium and Node.js) for | 
					
						
							|  |  |  |  | which potential security issues are not as widely known. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-29 16:01:05 -08:00
										 |  |  |  | [browser-window]: ../api/browser-window.md | 
					
						
							|  |  |  |  | [browser-view]: ../api/browser-view.md | 
					
						
							| 
									
										
										
										
											2018-06-21 16:39:07 +02:00
										 |  |  |  | [webview-tag]: ../api/webview-tag.md | 
					
						
							| 
									
										
										
										
											2018-07-31 11:40:26 -07:00
										 |  |  |  | [web-contents]: ../api/web-contents.md | 
					
						
							| 
									
										
										
										
											2018-08-09 17:04:03 +02:00
										 |  |  |  | [new-window]: ../api/web-contents.md#event-new-window | 
					
						
							|  |  |  |  | [will-navigate]: ../api/web-contents.md#event-will-navigate | 
					
						
							| 
									
										
										
										
											2019-02-27 19:09:38 +01:00
										 |  |  |  | [open-external]: ../api/shell.md#shellopenexternalurl-options-callback | 
					
						
							| 
									
										
										
										
											2019-04-05 20:41:05 +02:00
										 |  |  |  | [sandbox]: ../api/sandbox-option.md | 
					
						
							| 
									
										
										
										
											2019-09-13 21:12:14 -04:00
										 |  |  |  | [responsible-disclosure]: https://en.wikipedia.org/wiki/Responsible_disclosure |