зеркало из https://github.com/electron/electron.git
docs: update checklists (#32902)
This commit is contained in:
Родитель
c75ec2e689
Коммит
cc0eb7b908
|
@ -1,3 +1,11 @@
|
|||
---
|
||||
title: Performance
|
||||
description: A set of guidelines for building performant Electron apps
|
||||
slug: performance
|
||||
hide_title: true
|
||||
toc_max_heading_level: 3
|
||||
---
|
||||
|
||||
# Performance
|
||||
|
||||
Developers frequently ask about strategies to optimize the performance of
|
||||
|
@ -49,7 +57,7 @@ at once, consider the [Chrome Tracing](https://www.chromium.org/developers/how-t
|
|||
* [Get Started With Analyzing Runtime Performance][chrome-devtools-tutorial]
|
||||
* [Talk: "Visual Studio Code - The First Second"][vscode-first-second]
|
||||
|
||||
## Checklist
|
||||
## Checklist: Performance recommendations
|
||||
|
||||
Chances are that your app could be a little leaner, faster, and generally less
|
||||
resource-hungry if you attempt these steps.
|
||||
|
@ -62,7 +70,7 @@ resource-hungry if you attempt these steps.
|
|||
6. [Unnecessary or blocking network requests](#6-unnecessary-or-blocking-network-requests)
|
||||
7. [Bundle your code](#7-bundle-your-code)
|
||||
|
||||
## 1) Carelessly including modules
|
||||
### 1. Carelessly including modules
|
||||
|
||||
Before adding a Node.js module to your application, examine said module. How
|
||||
many dependencies does that module include? What kind of resources does
|
||||
|
@ -70,7 +78,7 @@ it need to simply be called in a `require()` statement? You might find
|
|||
that the module with the most downloads on the NPM package registry or the most stars on GitHub
|
||||
is not in fact the leanest or smallest one available.
|
||||
|
||||
### Why?
|
||||
#### Why?
|
||||
|
||||
The reasoning behind this recommendation is best illustrated with a real-world
|
||||
example. During the early days of Electron, reliable detection of network
|
||||
|
@ -99,7 +107,7 @@ running Linux might be bad news for your app's performance. In this particular
|
|||
example, the correct solution was to use no module at all, and to instead use
|
||||
connectivity checks included in later versions of Chromium.
|
||||
|
||||
### How?
|
||||
#### How?
|
||||
|
||||
When considering a module, we recommend that you check:
|
||||
|
||||
|
@ -128,7 +136,7 @@ In this example, on the author's machine, we saw that loading `request` took
|
|||
almost half a second, whereas `node-fetch` took dramatically less memory
|
||||
and less than 50ms.
|
||||
|
||||
## 2) Loading and running code too soon
|
||||
### 2. Loading and running code too soon
|
||||
|
||||
If you have expensive setup operations, consider deferring those. Inspect all
|
||||
the work being executed right after the application starts. Instead of firing
|
||||
|
@ -141,7 +149,7 @@ using the same strategy _and_ are using sizable modules that you do not
|
|||
immediately need, apply the same strategy and defer loading to a more
|
||||
opportune time.
|
||||
|
||||
### Why?
|
||||
#### Why?
|
||||
|
||||
Loading modules is a surprisingly expensive operation, especially on Windows.
|
||||
When your app starts, it should not make users wait for operations that are
|
||||
|
@ -157,14 +165,14 @@ immediately display the file to you without any code highlighting, prioritizing
|
|||
your ability to interact with the text. Once it has done that work, it will
|
||||
move on to code highlighting.
|
||||
|
||||
### How?
|
||||
#### How?
|
||||
|
||||
Let's consider an example and assume that your application is parsing files
|
||||
in the fictitious `.foo` format. In order to do that, it relies on the
|
||||
equally fictitious `foo-parser` module. In traditional Node.js development,
|
||||
you might write code that eagerly loads dependencies:
|
||||
|
||||
```js
|
||||
```js title='parser.js'
|
||||
const fs = require('fs')
|
||||
const fooParser = require('foo-parser')
|
||||
|
||||
|
@ -187,7 +195,7 @@ In the above example, we're doing a lot of work that's being executed as soon
|
|||
as the file is loaded. Do we need to get parsed files right away? Could we
|
||||
do this work a little later, when `getParsedFiles()` is actually called?
|
||||
|
||||
```js
|
||||
```js title='parser.js'
|
||||
// "fs" is likely already being loaded, so the `require()` call is cheap
|
||||
const fs = require('fs')
|
||||
|
||||
|
@ -223,7 +231,7 @@ module.exports = { parser }
|
|||
In short, allocate resources "just in time" rather than allocating them all
|
||||
when your app starts.
|
||||
|
||||
## 3) Blocking the main process
|
||||
### 3. Blocking the main process
|
||||
|
||||
Electron's main process (sometimes called "browser process") is special: It is
|
||||
the parent process to all your app's other processes and the primary process
|
||||
|
@ -235,7 +243,7 @@ Under no circumstances should you block this process and the UI thread with
|
|||
long-running operations. Blocking the UI thread means that your entire app
|
||||
will freeze until the main process is ready to continue processing.
|
||||
|
||||
### Why?
|
||||
#### Why?
|
||||
|
||||
The main process and its UI thread are essentially the control tower for major
|
||||
operations inside your app. When the operating system tells your app about a
|
||||
|
@ -246,31 +254,31 @@ the GPU process about that – once again going through the main process.
|
|||
Electron and Chromium are careful to put heavy disk I/O and CPU-bound operations
|
||||
onto new threads to avoid blocking the UI thread. You should do the same.
|
||||
|
||||
### How?
|
||||
#### How?
|
||||
|
||||
Electron's powerful multi-process architecture stands ready to assist you with
|
||||
your long-running tasks, but also includes a small number of performance traps.
|
||||
|
||||
1) For long running CPU-heavy tasks, make use of
|
||||
1. For long running CPU-heavy tasks, make use of
|
||||
[worker threads][worker-threads], consider moving them to the BrowserWindow, or
|
||||
(as a last resort) spawn a dedicated process.
|
||||
|
||||
2) Avoid using the synchronous IPC and the `remote` module as much as possible.
|
||||
While there are legitimate use cases, it is far too easy to unknowingly block
|
||||
the UI thread using the `remote` module.
|
||||
2. Avoid using the synchronous IPC and the `@electron/remote` module as much
|
||||
as possible. While there are legitimate use cases, it is far too easy to
|
||||
unknowingly block the UI thread.
|
||||
|
||||
3) Avoid using blocking I/O operations in the main process. In short, whenever
|
||||
3. Avoid using blocking I/O operations in the main process. In short, whenever
|
||||
core Node.js modules (like `fs` or `child_process`) offer a synchronous or an
|
||||
asynchronous version, you should prefer the asynchronous and non-blocking
|
||||
variant.
|
||||
|
||||
## 4) Blocking the renderer process
|
||||
### 4. Blocking the renderer process
|
||||
|
||||
Since Electron ships with a current version of Chrome, you can make use of the
|
||||
latest and greatest features the Web Platform offers to defer or offload heavy
|
||||
operations in a way that keeps your app smooth and responsive.
|
||||
|
||||
### Why?
|
||||
#### Why?
|
||||
|
||||
Your app probably has a lot of JavaScript to run in the renderer process. The
|
||||
trick is to execute operations as quickly as possible without taking away
|
||||
|
@ -280,7 +288,7 @@ at 60fps.
|
|||
Orchestrating the flow of operations in your renderer's code is
|
||||
particularly useful if users complain about your app sometimes "stuttering".
|
||||
|
||||
### How?
|
||||
#### How?
|
||||
|
||||
Generally speaking, all advice for building performant web apps for modern
|
||||
browsers apply to Electron's renderers, too. The two primary tools at your
|
||||
|
@ -300,14 +308,14 @@ some caveats to consider – consult Electron's
|
|||
for any operation that requires a lot of CPU power for an extended period of
|
||||
time.
|
||||
|
||||
## 5) Unnecessary polyfills
|
||||
### 5. Unnecessary polyfills
|
||||
|
||||
One of Electron's great benefits is that you know exactly which engine will
|
||||
parse your JavaScript, HTML, and CSS. If you're re-purposing code that was
|
||||
written for the web at large, make sure to not polyfill features included in
|
||||
Electron.
|
||||
|
||||
### Why?
|
||||
#### Why?
|
||||
|
||||
When building a web application for today's Internet, the oldest environments
|
||||
dictate what features you can and cannot use. Even though Electron supports
|
||||
|
@ -323,7 +331,7 @@ It is rare for a JavaScript-based polyfill to be faster than the equivalent
|
|||
native feature in Electron. Do not slow down your Electron app by shipping your
|
||||
own version of standard web platform features.
|
||||
|
||||
### How?
|
||||
#### How?
|
||||
|
||||
Operate under the assumption that polyfills in current versions of Electron
|
||||
are unnecessary. If you have doubts, check [caniuse.com](https://caniuse.com/)
|
||||
|
@ -338,12 +346,12 @@ If you're using a transpiler/compiler like TypeScript, examine its configuration
|
|||
and ensure that you're targeting the latest ECMAScript version supported by
|
||||
Electron.
|
||||
|
||||
## 6) Unnecessary or blocking network requests
|
||||
### 6. Unnecessary or blocking network requests
|
||||
|
||||
Avoid fetching rarely changing resources from the internet if they could easily
|
||||
be bundled with your application.
|
||||
|
||||
### Why?
|
||||
#### Why?
|
||||
|
||||
Many users of Electron start with an entirely web-based app that they're
|
||||
turning into a desktop application. As web developers, we are used to loading
|
||||
|
@ -360,7 +368,7 @@ will take care of the rest.
|
|||
When building an Electron app, your users are better served if you download
|
||||
the fonts and include them in your app's bundle.
|
||||
|
||||
### How?
|
||||
#### How?
|
||||
|
||||
In an ideal world, your application wouldn't need the network to operate at
|
||||
all. To get there, you must understand what resources your app is downloading
|
||||
|
@ -387,21 +395,21 @@ without shipping an application update is a powerful strategy. For advanced
|
|||
control over how resources are being loaded, consider investing in
|
||||
[Service Workers][service-workers].
|
||||
|
||||
## 7) Bundle your code
|
||||
### 7. Bundle your code
|
||||
|
||||
As already pointed out in
|
||||
"[Loading and running code too soon](#2-loading-and-running-code-too-soon)",
|
||||
calling `require()` is an expensive operation. If you are able to do so,
|
||||
bundle your application's code into a single file.
|
||||
|
||||
### Why?
|
||||
#### Why?
|
||||
|
||||
Modern JavaScript development usually involves many files and modules. While
|
||||
that's perfectly fine for developing with Electron, we heavily recommend that
|
||||
you bundle all your code into one single file to ensure that the overhead
|
||||
included in calling `require()` is only paid once when your application loads.
|
||||
|
||||
### How?
|
||||
#### How?
|
||||
|
||||
There are numerous JavaScript bundlers out there and we know better than to
|
||||
anger the community by recommending one tool over another. We do however
|
||||
|
|
|
@ -1,6 +1,24 @@
|
|||
# Security, Native Capabilities, and Your Responsibility
|
||||
---
|
||||
title: Security
|
||||
description: A set of guidelines for building secure Electron apps
|
||||
slug: security
|
||||
hide_title: true
|
||||
toc_max_heading_level: 3
|
||||
---
|
||||
# Security
|
||||
|
||||
As web developers, we usually enjoy the strong security net of the browser -
|
||||
:::info Reporting security issues
|
||||
For information on how to properly disclose an Electron vulnerability,
|
||||
see [SECURITY.md](https://github.com/electron/electron/tree/main/SECURITY.md).
|
||||
|
||||
For upstream Chromium vulnerabilities: Electron keeps up to date with alternating
|
||||
Chromium releases. For more information, see the
|
||||
[Electron Release Timelines](../tutorial/electron-timelines.md) document.
|
||||
:::
|
||||
|
||||
## Preface
|
||||
|
||||
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
|
||||
|
@ -17,20 +35,12 @@ With that in mind, be aware that displaying arbitrary content from untrusted
|
|||
sources poses a severe security risk that Electron is not intended to handle.
|
||||
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
|
||||
integration) — if your application executes code from an online source, it is
|
||||
your responsibility to ensure that the code is not malicious.
|
||||
|
||||
## Reporting Security Issues
|
||||
## General guidelines
|
||||
|
||||
For information on how to properly disclose an Electron vulnerability,
|
||||
see [SECURITY.md](https://github.com/electron/electron/tree/main/SECURITY.md)
|
||||
|
||||
## Chromium Security Issues and Upgrades
|
||||
|
||||
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).
|
||||
|
||||
## Security Is Everyone's Responsibility
|
||||
### Security is everyone's responsibility
|
||||
|
||||
It is important to remember that the security of your Electron application is
|
||||
the result of the overall security of the framework foundation
|
||||
|
@ -56,7 +66,7 @@ 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
|
||||
to adopt secure software development best practices and perform security testing.
|
||||
|
||||
## Isolation For Untrusted Content
|
||||
### 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
|
||||
|
@ -65,72 +75,74 @@ 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.
|
||||
|
||||
> :warning: Under no circumstances should you load and execute remote code with
|
||||
:::warning
|
||||
Under no circumstances should you load and execute remote code with
|
||||
Node.js integration enabled. Instead, use only local files (packaged together
|
||||
with your application) to execute Node.js code. To display remote content, use
|
||||
the [`<webview>`][webview-tag] tag or [`BrowserView`][browser-view], make sure
|
||||
to disable the `nodeIntegration` and enable `contextIsolation`.
|
||||
:::
|
||||
|
||||
## Electron Security Warnings
|
||||
|
||||
From Electron 2.0 on, developers will see warnings and recommendations printed
|
||||
to the developer console. They only show up when the binary's name is Electron,
|
||||
indicating that a developer is currently looking at the console.
|
||||
:::info Electron security warnings
|
||||
Security warnings and recommendations are printed to the developer console.
|
||||
They only show up when the binary's name is Electron, 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
|
||||
## Checklist: Security recommendations
|
||||
|
||||
You should at least follow these steps to improve the security of your application:
|
||||
|
||||
1. [Only load secure content](#1-only-load-secure-content)
|
||||
2. [Disable the Node.js integration in all renderers that display remote content](#2-do-not-enable-nodejs-integration-for-remote-content)
|
||||
3. [Enable context isolation in all renderers that display remote content](#3-enable-context-isolation-for-remote-content)
|
||||
4. [Enable sandboxing](#4-enable-sandboxing)
|
||||
4. [Enable process sandboxing](#4-enable-process-sandboxing)
|
||||
5. [Use `ses.setPermissionRequestHandler()` in all sessions that load remote content](#5-handle-session-permission-requests-from-remote-content)
|
||||
6. [Do not disable `webSecurity`](#6-do-not-disable-websecurity)
|
||||
7. [Define a `Content-Security-Policy`](#7-define-a-content-security-policy) and use restrictive rules (i.e. `script-src 'self'`)
|
||||
8. [Do not set `allowRunningInsecureContent` to `true`](#8-do-not-set-allowrunninginsecurecontent-to-true)
|
||||
8. [Do not enable `allowRunningInsecureContent`](#8-do-not-enable-allowrunninginsecurecontent)
|
||||
9. [Do not enable experimental features](#9-do-not-enable-experimental-features)
|
||||
10. [Do not use `enableBlinkFeatures`](#10-do-not-use-enableblinkfeatures)
|
||||
11. [`<webview>`: Do not use `allowpopups`](#11-do-not-use-allowpopups)
|
||||
11. [`<webview>`: Do not use `allowpopups`](#11-do-not-use-allowpopups-for-webviews)
|
||||
12. [`<webview>`: Verify options and params](#12-verify-webview-options-before-creation)
|
||||
13. [Disable or limit navigation](#13-disable-or-limit-navigation)
|
||||
14. [Disable or limit creation of new windows](#14-disable-or-limit-creation-of-new-windows)
|
||||
15. [Do not use `openExternal` with untrusted content](#15-do-not-use-openexternal-with-untrusted-content)
|
||||
15. [Do not use `shell.openExternal` with untrusted content](#15-do-not-use-shellopenexternal-with-untrusted-content)
|
||||
16. [Use a current version of Electron](#16-use-a-current-version-of-electron)
|
||||
|
||||
To automate the detection of misconfigurations and insecure patterns, it is
|
||||
possible to use
|
||||
[electronegativity](https://github.com/doyensec/electronegativity). For
|
||||
[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)
|
||||
developers and auditors](https://doyensec.com/resources/us-17-Carettoni-Electronegativity-A-Study-Of-Electron-Security-wp.pdf).
|
||||
|
||||
## 1) Only Load Secure Content
|
||||
### 1. Only load secure content
|
||||
|
||||
Any resources not included with your application should be loaded using a
|
||||
secure protocol like `HTTPS`. In other words, do not use insecure protocols
|
||||
like `HTTP`. Similarly, we recommend the use of `WSS` over `WS`, `FTPS` over
|
||||
`FTP`, and so on.
|
||||
|
||||
### Why?
|
||||
#### Why?
|
||||
|
||||
`HTTPS` has three main benefits:
|
||||
|
||||
1) It authenticates the remote server, ensuring your app connects to the correct
|
||||
1. It authenticates the remote server, ensuring your app connects to the correct
|
||||
host instead of an impersonator.
|
||||
2) It ensures data integrity, asserting that the data was not modified while in
|
||||
1. It ensures data integrity, asserting that the data was not modified while in
|
||||
transit between your application and the host.
|
||||
3) It encrypts the traffic between your user and the destination host, making it
|
||||
1. 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
|
||||
the host.
|
||||
|
||||
### How?
|
||||
#### How?
|
||||
|
||||
```js
|
||||
```js title='main.js (Main Process)'
|
||||
// Bad
|
||||
browserWindow.loadURL('http://example.com')
|
||||
|
||||
|
@ -138,7 +150,7 @@ browserWindow.loadURL('http://example.com')
|
|||
browserWindow.loadURL('https://example.com')
|
||||
```
|
||||
|
||||
```html
|
||||
```html title='index.html (Renderer Process)'
|
||||
<!-- Bad -->
|
||||
<script crossorigin src="http://example.com/react.js"></script>
|
||||
<link rel="stylesheet" href="http://example.com/style.css">
|
||||
|
@ -148,9 +160,11 @@ browserWindow.loadURL('https://example.com')
|
|||
<link rel="stylesheet" href="https://example.com/style.css">
|
||||
```
|
||||
|
||||
## 2) Do not enable Node.js Integration for Remote Content
|
||||
### 2. Do not enable Node.js integration for remote content
|
||||
|
||||
_This recommendation is the default behavior in Electron since 5.0.0._
|
||||
:::info
|
||||
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
|
||||
([`BrowserWindow`][browser-window], [`BrowserView`][browser-view], or
|
||||
|
@ -163,7 +177,7 @@ After this, you can grant additional permissions for specific hosts. For example
|
|||
if you are opening a BrowserWindow pointed at `https://example.com/`, you can
|
||||
give that website exactly the abilities it needs, but no more.
|
||||
|
||||
### Why?
|
||||
#### Why?
|
||||
|
||||
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.
|
||||
|
@ -172,12 +186,13 @@ 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.
|
||||
|
||||
### How?
|
||||
#### How?
|
||||
|
||||
```js
|
||||
```js title='main.js (Main Process)'
|
||||
// Bad
|
||||
const mainWindow = new BrowserWindow({
|
||||
webPreferences: {
|
||||
contextIsolation: false,
|
||||
nodeIntegration: true,
|
||||
nodeIntegrationInWorker: true
|
||||
}
|
||||
|
@ -186,7 +201,7 @@ const mainWindow = new BrowserWindow({
|
|||
mainWindow.loadURL('https://example.com')
|
||||
```
|
||||
|
||||
```js
|
||||
```js title='main.js (Main Process)'
|
||||
// Good
|
||||
const mainWindow = new BrowserWindow({
|
||||
webPreferences: {
|
||||
|
@ -197,7 +212,7 @@ const mainWindow = new BrowserWindow({
|
|||
mainWindow.loadURL('https://example.com')
|
||||
```
|
||||
|
||||
```html
|
||||
```html title='index.html (Renderer Process)'
|
||||
<!-- Bad -->
|
||||
<webview nodeIntegration src="page.html"></webview>
|
||||
|
||||
|
@ -208,21 +223,13 @@ mainWindow.loadURL('https://example.com')
|
|||
When disabling Node.js integration, you can still expose APIs to your website that
|
||||
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.
|
||||
API to remotely loaded content via the [contextBridge API](../api/context-bridge.md).
|
||||
|
||||
In the following example preload script, the later loaded website will have
|
||||
access to a `window.readConfig()` method, but no Node.js features.
|
||||
### 3. Enable Context Isolation for remote content
|
||||
|
||||
```js
|
||||
const { readFileSync } = require('fs')
|
||||
|
||||
window.readConfig = () => {
|
||||
const data = readFileSync('./config.json')
|
||||
return data
|
||||
}
|
||||
```
|
||||
|
||||
## 3) Enable Context Isolation for Remote Content
|
||||
:::info
|
||||
This recommendation is the default behavior in Electron since 12.0.0.
|
||||
:::
|
||||
|
||||
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
|
||||
|
@ -235,48 +242,42 @@ to enable this behavior.
|
|||
Even when `nodeIntegration: false` is used, to truly enforce strong isolation
|
||||
and prevent the use of Node primitives `contextIsolation` **must** also be used.
|
||||
|
||||
### Why & How?
|
||||
|
||||
:::info
|
||||
For more information on what `contextIsolation` is and how to enable it please
|
||||
see our dedicated [Context Isolation](context-isolation.md) document.
|
||||
:::info
|
||||
|
||||
## 4) Enable Sandboxing
|
||||
### 4. Enable process sandboxing
|
||||
|
||||
[Sandboxing](sandbox.md) is a Chromium feature that uses the operating system to
|
||||
[Sandboxing](https://chromium.googlesource.com/chromium/src/+/HEAD/docs/design/sandbox.md)
|
||||
is a Chromium feature that uses the operating system to
|
||||
significantly limit what renderer processes have access to. You should enable
|
||||
the sandbox in all renderers. Loading, reading or processing any untrusted
|
||||
content in an unsandboxed process, including the main process, is not advised.
|
||||
|
||||
### How?
|
||||
:::info
|
||||
For more information on what `contextIsolation` is and how to enable it please
|
||||
see our dedicated [Process Sandboxing](sandbox.md) document.
|
||||
:::info
|
||||
|
||||
When creating a window, pass the `sandbox: true` option in `webPreferences`:
|
||||
### 5. Handle session permission requests from remote content
|
||||
|
||||
```js
|
||||
const win = new BrowserWindow({
|
||||
webPreferences: {
|
||||
sandbox: true
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## 5) Handle Session Permission Requests From Remote Content
|
||||
|
||||
You may have seen permission requests while using Chrome: They pop up whenever
|
||||
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?
|
||||
#### 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?
|
||||
#### How?
|
||||
|
||||
```js
|
||||
```js title='main.js (Main Process)'
|
||||
const { session } = require('electron')
|
||||
|
||||
session
|
||||
|
@ -297,9 +298,11 @@ session
|
|||
})
|
||||
```
|
||||
|
||||
## 6) Do Not Disable WebSecurity
|
||||
### 6. Do not disable `webSecurity`
|
||||
|
||||
_Recommendation is Electron's default_
|
||||
:::info
|
||||
This recommendation is Electron's default.
|
||||
:::
|
||||
|
||||
You may have already guessed that disabling the `webSecurity` property on a
|
||||
renderer process ([`BrowserWindow`][browser-window],
|
||||
|
@ -308,15 +311,15 @@ security features.
|
|||
|
||||
Do not disable `webSecurity` in production applications.
|
||||
|
||||
### Why?
|
||||
#### 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?
|
||||
#### How?
|
||||
|
||||
```js
|
||||
```js title='main.js (Main Process)'
|
||||
// Bad
|
||||
const mainWindow = new BrowserWindow({
|
||||
webPreferences: {
|
||||
|
@ -325,12 +328,12 @@ const mainWindow = new BrowserWindow({
|
|||
})
|
||||
```
|
||||
|
||||
```js
|
||||
```js title='main.js (Main Process)'
|
||||
// Good
|
||||
const mainWindow = new BrowserWindow()
|
||||
```
|
||||
|
||||
```html
|
||||
```html title='index.html (Renderer Process)'
|
||||
<!-- Bad -->
|
||||
<webview disablewebsecurity src="page.html"></webview>
|
||||
|
||||
|
@ -338,13 +341,13 @@ const mainWindow = new BrowserWindow()
|
|||
<webview src="page.html"></webview>
|
||||
```
|
||||
|
||||
## 7) Define a Content Security Policy
|
||||
### 7. Define a Content Security Policy
|
||||
|
||||
A Content Security Policy (CSP) is an additional layer of protection against
|
||||
cross-site-scripting attacks and data injection attacks. We recommend that they
|
||||
be enabled by any website you load inside Electron.
|
||||
|
||||
### Why?
|
||||
#### Why?
|
||||
|
||||
CSP allows the server serving content to restrict and control the resources
|
||||
Electron can load for that given web page. `https://example.com` should
|
||||
|
@ -352,6 +355,8 @@ be allowed to load scripts from the origins you defined while scripts from
|
|||
`https://evil.attacker.com` should not be allowed to run. Defining a CSP is an
|
||||
easy way to improve your application's security.
|
||||
|
||||
#### How?
|
||||
|
||||
The following CSP will allow Electron to execute scripts from the current
|
||||
website and from `apis.example.com`.
|
||||
|
||||
|
@ -363,14 +368,14 @@ Content-Security-Policy: '*'
|
|||
Content-Security-Policy: script-src 'self' https://apis.example.com
|
||||
```
|
||||
|
||||
### CSP HTTP Header
|
||||
#### CSP HTTP headers
|
||||
|
||||
Electron respects the [`Content-Security-Policy` HTTP header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy)
|
||||
which can be set using Electron's
|
||||
[`webRequest.onHeadersReceived`](../api/web-request.md#webrequestonheadersreceivedfilter-listener)
|
||||
handler:
|
||||
|
||||
```javascript
|
||||
```javascript title='main.js (Main Process)'
|
||||
const { session } = require('electron')
|
||||
|
||||
session.defaultSession.webRequest.onHeadersReceived((details, callback) => {
|
||||
|
@ -383,20 +388,22 @@ session.defaultSession.webRequest.onHeadersReceived((details, callback) => {
|
|||
})
|
||||
```
|
||||
|
||||
### CSP Meta Tag
|
||||
#### CSP meta tag
|
||||
|
||||
CSP's preferred delivery mechanism is an HTTP header, however it is not possible
|
||||
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:
|
||||
be useful in some cases to set a policy on a page directly in the markup using a
|
||||
`<meta>` tag:
|
||||
|
||||
```html
|
||||
```html title='index.html (Renderer Process)'
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'none'">
|
||||
```
|
||||
|
||||
## 8) Do Not Set `allowRunningInsecureContent` to `true`
|
||||
### 8. Do not enable `allowRunningInsecureContent`
|
||||
|
||||
_Recommendation is Electron's default_
|
||||
:::info
|
||||
This recommendation is Electron's default.
|
||||
:::
|
||||
|
||||
By default, Electron will not allow websites loaded over `HTTPS` to load and
|
||||
execute scripts, CSS, or plugins from insecure sources (`HTTP`). Setting the
|
||||
|
@ -405,15 +412,15 @@ 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?
|
||||
#### Why?
|
||||
|
||||
Loading content over `HTTPS` assures the authenticity and integrity
|
||||
of the loaded resources while encrypting the traffic itself. See the section on
|
||||
[only displaying secure content](#1-only-load-secure-content) for more details.
|
||||
|
||||
### How?
|
||||
#### How?
|
||||
|
||||
```js
|
||||
```js title='main.js (Main Process)'
|
||||
// Bad
|
||||
const mainWindow = new BrowserWindow({
|
||||
webPreferences: {
|
||||
|
@ -422,19 +429,21 @@ const mainWindow = new BrowserWindow({
|
|||
})
|
||||
```
|
||||
|
||||
```js
|
||||
```js title='main.js (Main Process)'
|
||||
// Good
|
||||
const mainWindow = new BrowserWindow({})
|
||||
```
|
||||
|
||||
## 9) Do Not Enable Experimental Features
|
||||
### 9. Do not enable experimental features
|
||||
|
||||
_Recommendation is Electron's default_
|
||||
:::info
|
||||
This recommendation is Electron's default.
|
||||
:::
|
||||
|
||||
Advanced users of Electron can enable experimental Chromium features using the
|
||||
`experimentalFeatures` property.
|
||||
|
||||
### Why?
|
||||
#### Why?
|
||||
|
||||
Experimental features are, as the name suggests, experimental and have not been
|
||||
enabled for all Chromium users. Furthermore, their impact on Electron as a whole
|
||||
|
@ -443,9 +452,9 @@ has likely not been tested.
|
|||
Legitimate use cases exist, but unless you know what you are doing, you should
|
||||
not enable this property.
|
||||
|
||||
### How?
|
||||
#### How?
|
||||
|
||||
```js
|
||||
```js title='main.js (Main Process)'
|
||||
// Bad
|
||||
const mainWindow = new BrowserWindow({
|
||||
webPreferences: {
|
||||
|
@ -454,20 +463,22 @@ const mainWindow = new BrowserWindow({
|
|||
})
|
||||
```
|
||||
|
||||
```js
|
||||
```js title='main.js (Main Process)'
|
||||
// Good
|
||||
const mainWindow = new BrowserWindow({})
|
||||
```
|
||||
|
||||
## 10) Do Not Use `enableBlinkFeatures`
|
||||
### 10. Do not use `enableBlinkFeatures`
|
||||
|
||||
_Recommendation is Electron's default_
|
||||
:::info
|
||||
This recommendation is Electron's default.
|
||||
:::
|
||||
|
||||
Blink is the name of the rendering engine behind Chromium. As with
|
||||
`experimentalFeatures`, the `enableBlinkFeatures` property allows developers to
|
||||
enable features that have been disabled by default.
|
||||
|
||||
### Why?
|
||||
#### 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
|
||||
|
@ -475,9 +486,9 @@ 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?
|
||||
#### How?
|
||||
|
||||
```js
|
||||
```js title='main.js (Main Process)'
|
||||
// Bad
|
||||
const mainWindow = new BrowserWindow({
|
||||
webPreferences: {
|
||||
|
@ -486,14 +497,16 @@ const mainWindow = new BrowserWindow({
|
|||
})
|
||||
```
|
||||
|
||||
```js
|
||||
```js title='main.js (Main Process)'
|
||||
// Good
|
||||
const mainWindow = new BrowserWindow()
|
||||
```
|
||||
|
||||
## 11) Do Not Use `allowpopups`
|
||||
### 11. Do not use `allowpopups` for WebViews
|
||||
|
||||
_Recommendation is Electron's default_
|
||||
:::info
|
||||
This recommendation is Electron's default.
|
||||
:::
|
||||
|
||||
If you are using [`<webview>`][webview-tag], you might need the pages and scripts
|
||||
loaded in your `<webview>` tag to open new windows. The `allowpopups` attribute
|
||||
|
@ -501,16 +514,16 @@ enables them to create new [`BrowserWindows`][browser-window] using the
|
|||
`window.open()` method. `<webview>` tags are otherwise not allowed to create new
|
||||
windows.
|
||||
|
||||
### Why?
|
||||
#### Why?
|
||||
|
||||
If you do not need popups, you are better off not allowing the creation of
|
||||
new [`BrowserWindows`][browser-window] by default. This follows the principle
|
||||
of minimally required access: Don't let a website create new popups unless
|
||||
you know it needs that feature.
|
||||
|
||||
### How?
|
||||
#### How?
|
||||
|
||||
```html
|
||||
```html title='index.html (Renderer Process)'
|
||||
<!-- Bad -->
|
||||
<webview allowpopups src="page.html"></webview>
|
||||
|
||||
|
@ -518,7 +531,7 @@ you know it needs that feature.
|
|||
<webview src="page.html"></webview>
|
||||
```
|
||||
|
||||
## 12) Verify WebView Options Before Creation
|
||||
### 12. Verify WebView options before creation
|
||||
|
||||
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
|
||||
|
@ -528,7 +541,7 @@ 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
|
||||
security features.
|
||||
|
||||
### Why?
|
||||
#### Why?
|
||||
|
||||
Since `<webview>` live in the DOM, they can be created by a script running on your
|
||||
website even if Node.js integration is otherwise disabled.
|
||||
|
@ -538,13 +551,13 @@ a renderer process. In most cases, developers do not need to disable any of
|
|||
those features - and you should therefore not allow different configurations
|
||||
for newly created [`<webview>`][webview-tag] tags.
|
||||
|
||||
### How?
|
||||
#### How?
|
||||
|
||||
Before a [`<webview>`][webview-tag] tag is attached, Electron will fire the
|
||||
`will-attach-webview` event on the hosting `webContents`. Use the event to
|
||||
prevent the creation of `webViews` with possibly insecure options.
|
||||
|
||||
```js
|
||||
```js title='main.js (Main Process)'
|
||||
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
|
||||
|
@ -562,16 +575,16 @@ app.on('web-contents-created', (event, contents) => {
|
|||
})
|
||||
```
|
||||
|
||||
Again, this list merely minimizes the risk, it does not remove it. If your goal
|
||||
Again, this list merely minimizes the risk, but does not remove it. If your goal
|
||||
is to display a website, a browser will be a more secure option.
|
||||
|
||||
## 13) Disable or limit navigation
|
||||
### 13. Disable or limit navigation
|
||||
|
||||
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?
|
||||
#### 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
|
||||
|
@ -584,7 +597,7 @@ 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?
|
||||
#### 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
|
||||
|
@ -595,7 +608,7 @@ We recommend that you use Node's parser for URLs. Simple string comparisons can
|
|||
sometimes be fooled - a `startsWith('https://example.com')` test would let
|
||||
`https://example.com.attacker.com` through.
|
||||
|
||||
```js
|
||||
```js title='main.js (Main Process)'
|
||||
const URL = require('url').URL
|
||||
|
||||
app.on('web-contents-created', (event, contents) => {
|
||||
|
@ -609,12 +622,12 @@ app.on('web-contents-created', (event, contents) => {
|
|||
})
|
||||
```
|
||||
|
||||
## 14) Disable or limit creation of new windows
|
||||
### 14. Disable or limit creation of new windows
|
||||
|
||||
If you have a known set of windows, it's a good idea to limit the creation of
|
||||
additional windows in your app.
|
||||
|
||||
### Why?
|
||||
#### 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,
|
||||
|
@ -627,7 +640,7 @@ 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?
|
||||
#### How?
|
||||
|
||||
[`webContents`][web-contents] will delegate to its [window open
|
||||
handler][window-open-handler] before creating new windows. The handler will
|
||||
|
@ -635,7 +648,7 @@ receive, amongst other parameters, the `url` the window was requested to open
|
|||
and the options used to create it. We recommend that you register a handler to
|
||||
monitor the creation of windows, and deny any unexpected window creation.
|
||||
|
||||
```js
|
||||
```js title='main.js (Main Process)'
|
||||
const { shell } = require('electron')
|
||||
|
||||
app.on('web-contents-created', (event, contents) => {
|
||||
|
@ -656,40 +669,40 @@ app.on('web-contents-created', (event, contents) => {
|
|||
})
|
||||
```
|
||||
|
||||
## 15) Do not use `openExternal` with untrusted content
|
||||
### 15. Do not use `shell.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.
|
||||
The shell module's [`openExternal`][open-external] API 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?
|
||||
#### 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?
|
||||
#### How?
|
||||
|
||||
```js
|
||||
```js title='main.js (Main Process)'
|
||||
// Bad
|
||||
const { shell } = require('electron')
|
||||
shell.openExternal(USER_CONTROLLED_DATA_HERE)
|
||||
```
|
||||
|
||||
```js
|
||||
```js title='main.js (Main Process)'
|
||||
// Good
|
||||
const { shell } = require('electron')
|
||||
shell.openExternal('https://example.com/index.html')
|
||||
```
|
||||
|
||||
## 16) Use a current version of Electron
|
||||
### 16. 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?
|
||||
#### 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
|
||||
|
@ -705,6 +718,13 @@ 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.
|
||||
|
||||
#### How?
|
||||
|
||||
Migrate your app one major version at a time, while referring to Electron's
|
||||
[Breaking Changes][breaking-changes] document to see if any code needs to
|
||||
be updated.
|
||||
|
||||
[breaking-changes]: ../breaking-changes.md
|
||||
[browser-window]: ../api/browser-window.md
|
||||
[browser-view]: ../api/browser-view.md
|
||||
[webview-tag]: ../api/webview-tag.md
|
||||
|
@ -712,5 +732,4 @@ which potential security issues are not as widely known.
|
|||
[window-open-handler]: ../api/web-contents.md#contentssetwindowopenhandlerhandler
|
||||
[will-navigate]: ../api/web-contents.md#event-will-navigate
|
||||
[open-external]: ../api/shell.md#shellopenexternalurl-options
|
||||
[sandbox]: ../tutorial/sandbox.md
|
||||
[responsible-disclosure]: https://en.wikipedia.org/wiki/Responsible_disclosure
|
||||
|
|
Загрузка…
Ссылка в новой задаче