❤️ More feedback
This commit is contained in:
parent
8f685e9329
commit
1e1729adad
1 changed files with 62 additions and 68 deletions
|
@ -13,7 +13,7 @@ can access the filesystem, user shell, and more. This allows you to build
|
||||||
high quality native applications, but the inherent security risks scale with
|
high quality native applications, but the inherent security risks scale with
|
||||||
the additional powers granted to your code.
|
the additional powers granted to your code.
|
||||||
|
|
||||||
With that in mind, be aware that displaying arbitrary content from un-trusted
|
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.
|
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)
|
In fact, the most popular Electron apps (Atom, Slack, Visual Studio Code, etc)
|
||||||
display primarily local content (or trusted, secure remote content without Node
|
display primarily local content (or trusted, secure remote content without Node
|
||||||
|
@ -58,14 +58,14 @@ the [`webview`](web-view) tag and make sure to disable the `nodeIntegration`.
|
||||||
|
|
||||||
This is not bulletproof, but at the least, you should attempt the following:
|
This is not bulletproof, but at the least, you should attempt the following:
|
||||||
|
|
||||||
* [Only display secure (https) content](#only-display-secure-content)
|
* [Only load secure content](#only-load-secure-content)
|
||||||
* [Disable the Node integration in all renderers that display remote content](#disable-node-integration-for-remote-content)
|
* [Disable the Node.js integration in all renderers that display remote content](#disable-node.js-integration-for-remote-content)
|
||||||
* [Enable context isolation in all renderers that display remote content](#enable-context-isolation-for-remote-content)
|
* [Enable context isolation in all renderers that display remote content](#enable-context-isolation-for-remote-content)
|
||||||
* [Use `ses.setPermissionRequestHandler()` in all sessions that load remote content](#handle-session-permission-requests-from-remote-content)
|
* [Use `ses.setPermissionRequestHandler()` in all sessions that load remote content](#handle-session-permission-requests-from-remote-content)
|
||||||
* [Do not disable `webSecurity`](#do-not-disable-websecurity)
|
* [Do not disable `webSecurity`](#do-not-disable-websecurity)
|
||||||
* [Define a `Content-Security-Policy`](#define-a-content-security-policy)
|
* [Define a `Content-Security-Policy`](#define-a-content-security-policy)
|
||||||
, and use restrictive rules (i.e. `script-src 'self'`)
|
and use restrictive rules (i.e. `script-src 'self'`)
|
||||||
* [Override and disable `eval`](#override-and-disable)
|
* [Override and disable `eval`](#override-and-disable-eval)
|
||||||
, which allows strings to be executed as code.
|
, which allows strings to be executed as code.
|
||||||
* [Do not set `allowRunningInsecureContent` to `true`](#do-not-set-allowRunningInsecureContent-to-true)
|
* [Do not set `allowRunningInsecureContent` to `true`](#do-not-set-allowRunningInsecureContent-to-true)
|
||||||
* [Do not enable experimental features](#do-not-enable-experimental-features)
|
* [Do not enable experimental features](#do-not-enable-experimental-features)
|
||||||
|
@ -74,25 +74,23 @@ This is not bulletproof, but at the least, you should attempt the following:
|
||||||
* [WebViews: Verify the options and params of all `<webview>` tags](#verify-webview-options-before-creation)
|
* [WebViews: Verify the options and params of all `<webview>` tags](#verify-webview-options-before-creation)
|
||||||
|
|
||||||
|
|
||||||
## Only Display Secure Content
|
## Only Load Secure Content
|
||||||
|
|
||||||
Any resources not included with your application should be loaded using a
|
Any resources not included with your application should be loaded using a
|
||||||
secure protocol like `HTTPS`. In other words, do not use insecure protocols
|
secure protocol like `HTTPS`. In other words, do not use insecure protocols
|
||||||
like
|
like `HTTP`. Similarly, we recommed the use of `WSS` over `WS`, `FTPS` over
|
||||||
|
`FTP`, and so on.
|
||||||
|
|
||||||
### Why?
|
### Why?
|
||||||
|
|
||||||
`HTTPS` has three main benefits:
|
`HTTPS` has three main benefits:
|
||||||
|
|
||||||
1) It authenticates the remote server, ensuring that the host is actually whom
|
1) It authenticates the remote server, ensuring your app connects to the correct
|
||||||
it claims to be. When loading a resource from an `HTTPS` host, it prevents
|
host instead of an impersonator.
|
||||||
an attacker from impersonating that host, thus ensuring that the computer
|
|
||||||
your app's users are connecting to is actually the host you wanted them to
|
|
||||||
connect to.
|
|
||||||
2) It ensures data integrity, asserting that the data was not modified while in
|
2) It ensures data integrity, asserting that the data was not modified while in
|
||||||
transit between your application and the host.
|
transit between your application and the host.
|
||||||
3) It encryps the traffic between your user and the destination host, making it
|
3) It encrypts the traffic between your user and the destination host, making it
|
||||||
more difficult to eavesdropping on the information sent between your app and
|
more difficult to eavesdrop on the information sent between your app and
|
||||||
the host.
|
the host.
|
||||||
|
|
||||||
### How?
|
### How?
|
||||||
|
@ -116,30 +114,27 @@ browserWindow.loadURL('https://my-website.com')
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Disable Node Integration for Remote Content
|
## Disable Node.js Integration for Remote Content
|
||||||
|
|
||||||
It is paramount that you disable Node integration in any renderer
|
It is paramount that you disable Node.js integration in any renderer
|
||||||
([`BrowserWindow`](browser-view), [`BrowserView`](browser-view), or
|
([`BrowserWindow`](browser-window), [`BrowserView`](browser-view), or
|
||||||
[`WebView`](web-view)) that loads remote content. The goal of disabling Node
|
[`WebView`](web-view)) that loads remote content. The goal is to limit the
|
||||||
integration is to limit the powers you grant to remote content, thus making it
|
powers you grant to remote content, thus making it dramatically more difficult
|
||||||
dramatically more difficult for an attacker to harm your users should they gain
|
for an attacker to harm your users should they gain the ability to execute
|
||||||
the ability to execute JavaScript on your website.
|
JavaScript on your website.
|
||||||
|
|
||||||
Disabling Node integration does not mean that you cannot grant additional
|
After this, you can grant additional permissions for specific hosts. For example,
|
||||||
powers to the website you are loading. If you are opening a
|
if you are opening a BrowserWindow pointed at `https://my-website.com/", you can
|
||||||
[`BrowserWindow`](browser-window) pointed at `https://my-website.com`, the
|
give that website exactly the abilities it needs, but no more.
|
||||||
goal is to give that website exactly the abilities it needs, but no more.
|
|
||||||
|
|
||||||
### Why?
|
### Why?
|
||||||
|
|
||||||
A cross-site-scripting (XSS) attack becomes dramatically more dangerous if an
|
A cross-site-scripting (XSS) attack is more dangerous if an attacker can jump
|
||||||
attacker can jump out of the renderer process and execute code on the user's
|
out of the renderer process and execute code on the user's computer.
|
||||||
computer. Cross-site-scripting attacks are fairly common - and while an issue,
|
Cross-site-scripting attacks are fairly common - and while an issue, their
|
||||||
their power is usually limited to messing with the website that they are
|
power is usually limited to messing with the website that they are executed on.
|
||||||
executed on. However, in a renderer process with Node.js integration enabled,
|
Disabling Node.js integration helps prevent an XSS from being escalated into a
|
||||||
an XSS attack becomes a whole different class of attack: A so-called "Remote
|
so-called "Remote Code Execution" (RCE) attack.
|
||||||
Code Execution" (RCE) attack. Disabling Node.js integration limits the power
|
|
||||||
of successful XSS attacks.
|
|
||||||
|
|
||||||
### How?
|
### How?
|
||||||
|
|
||||||
|
@ -169,7 +164,7 @@ mainWindow.loadURL('https://my-website.com')
|
||||||
<webview src="page.html"></webview>
|
<webview src="page.html"></webview>
|
||||||
```
|
```
|
||||||
|
|
||||||
When disabling Node integration, you can still expose APIs to your website that
|
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
|
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
|
to `require` and other Node.js features, allowing developers to expose a custom
|
||||||
API to remotely loaded content.
|
API to remotely loaded content.
|
||||||
|
@ -203,13 +198,13 @@ Context isolation allows each the scripts on running in the renderer to make
|
||||||
changes to its JavaScript environment without worrying about conflicting with
|
changes to its JavaScript environment without worrying about conflicting with
|
||||||
the scripts in the Electron API or the preload script.
|
the scripts in the Electron API or the preload script.
|
||||||
|
|
||||||
While still an experimental Electron feature, context isolation also adds an
|
While still an experimental Electron feature, context isolation adds an
|
||||||
additional layer of security by completely separating any Electron APIs and
|
additional layer of security. It creates a new JavaScript world for Electron
|
||||||
preload scripts from access by the scripts running in the renderer. At the
|
APIs and preload scripts.
|
||||||
same time, preload scripts continue to have access to the `document` and
|
|
||||||
`window` object, meaning that you are very likely not reduced in your ability
|
At the same time, preload scripts still have access to the `document` and
|
||||||
to use preload scripts. In other words, you're getting a decent return on a
|
`window` objects. In other words, you're getting a decent return on a likely
|
||||||
likely very small investment.
|
very small investment.
|
||||||
|
|
||||||
### How?
|
### How?
|
||||||
|
|
||||||
|
@ -285,15 +280,14 @@ session
|
||||||
## Define a Content Security Policy
|
## Define a Content Security Policy
|
||||||
|
|
||||||
A Content Security Policy (CSP) is an additional layer of protection against
|
A Content Security Policy (CSP) is an additional layer of protection against
|
||||||
cross-site-scripting attacks (XSS) and data injection attacks. They can be
|
cross-site-scripting attacks and data injection attacks. We recommend that they
|
||||||
enabled by websites and we recommend that any website you load inside Electron
|
be enabled by any website you load inside Electron.
|
||||||
does so.
|
|
||||||
|
|
||||||
### Why?
|
### Why?
|
||||||
|
|
||||||
CSP allows the server serving content to restrict and control the resources
|
CSP allows the server serving content to restrict and control the resources
|
||||||
Electron will load for that given web page. `https://your-page.com` should have
|
Electron can load for that given web page. `https://your-page.com` should
|
||||||
be allowed to scripts from the origins you defined, while scripts from
|
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
|
`https://evil.attacker.com` should not be allowed to run. Defining a CSP is an
|
||||||
easy way to improve your applications security.
|
easy way to improve your applications security.
|
||||||
|
|
||||||
|
@ -303,7 +297,7 @@ Electron respects [the `Content-Security-Policy` HTTP header](https://developer.
|
||||||
as well as the respective `<meta>` tag.
|
as well as the respective `<meta>` tag.
|
||||||
|
|
||||||
The following CSP will allow Electron to execute scripts from the current
|
The following CSP will allow Electron to execute scripts from the current
|
||||||
website as well as from `apis.mydomain.com`.
|
website and from `apis.mydomain.com`.
|
||||||
|
|
||||||
```txt
|
```txt
|
||||||
// Bad
|
// Bad
|
||||||
|
@ -324,8 +318,9 @@ that is not known in advance.
|
||||||
|
|
||||||
The `eval()` method has precisely one mission: To evaluate a series of
|
The `eval()` method has precisely one mission: To evaluate a series of
|
||||||
characters as JavaScript and execute it. It is a required method whenever you
|
characters as JavaScript and execute it. It is a required method whenever you
|
||||||
need to evaluate code that is known ahead of time. While legitimate use cases
|
need to evaluate code that is not known ahead of time. While legitimate use
|
||||||
exist, just like any other code generators, `eval()` is difficult to harden.
|
cases exist, just like any other code generators, `eval()` is difficult to
|
||||||
|
harden.
|
||||||
|
|
||||||
Generally speaking, it is easier to completely disable `eval()` than to make
|
Generally speaking, it is easier to completely disable `eval()` than to make
|
||||||
it bulletproof. Thus, if you do not need it, it is a good idea to disable it.
|
it bulletproof. Thus, if you do not need it, it is a good idea to disable it.
|
||||||
|
@ -352,10 +347,9 @@ subsequent resources via `HTTP` is also known as "mixed content".
|
||||||
|
|
||||||
### Why?
|
### Why?
|
||||||
|
|
||||||
See the section on [only displaying secure content](#only-display-secure-content)
|
Simply put, loading content over `HTTPS` assures the authenticity and integrity
|
||||||
for more details, but simply put, loading content over `HTTPS` assures the
|
of the loaded resources while encrypting the traffic itself. See the section on
|
||||||
authenticity and integrity of the loaded resources while encrypting the traffic
|
[only displaying secure content](#only-display-secure-content) for more details.
|
||||||
itself.
|
|
||||||
|
|
||||||
### How?
|
### How?
|
||||||
|
|
||||||
|
@ -411,7 +405,7 @@ const mainWindow = new BrowserWindow({})
|
||||||
|
|
||||||
_Recommendation is Electron's default_
|
_Recommendation is Electron's default_
|
||||||
|
|
||||||
Blink is the name of the rendering engine behind Chromium. Similarly to
|
Blink is the name of the rendering engine behind Chromium. As with
|
||||||
`experimentalFeatures`, the `blinkFeatures` property allows developers to
|
`experimentalFeatures`, the `blinkFeatures` property allows developers to
|
||||||
enable features that have been disabled by default.
|
enable features that have been disabled by default.
|
||||||
|
|
||||||
|
@ -444,18 +438,17 @@ const mainWindow = new BrowserWindow()
|
||||||
_Recommendation is Electron's default_
|
_Recommendation is Electron's default_
|
||||||
|
|
||||||
You may have already guessed that disabling the `webSecurity` property on a
|
You may have already guessed that disabling the `webSecurity` property on a
|
||||||
renderer process ([`BrowserWindow`](browser-view),
|
renderer process ([`BrowserWindow`](browser-window),
|
||||||
[`BrowserView`](browser-view), or [`WebView`](web-view)) disables crucial
|
[`BrowserView`](browser-view), or [`WebView`](web-view)) disables crucial
|
||||||
security features.
|
security features.
|
||||||
|
|
||||||
Legitimate use cases for this property exist in testing cases, but generally
|
Do not disable `webSecurity` in production applications.
|
||||||
speaking, `webSecurity` should never be disabled in any production application.
|
|
||||||
|
|
||||||
### Why?
|
### Why?
|
||||||
|
|
||||||
Disabling `webSecurity` will disable the same-origin policy as well as
|
Disabling `webSecurity` will disable the same-origin policy and set
|
||||||
implicitly setting the `allowRunningInsecureContent` property to `true`. In
|
`allowRunningInsecureContent` property to `true`. In other words, it allows
|
||||||
other words, it allows the execution of insecure code from different domains.
|
the execution of insecure code from different domains.
|
||||||
|
|
||||||
### How?
|
### How?
|
||||||
```js
|
```js
|
||||||
|
@ -465,6 +458,7 @@ const mainWindow = new BrowserWindow({
|
||||||
webSecurity: false
|
webSecurity: false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
```
|
||||||
|
|
||||||
```js
|
```js
|
||||||
// Good
|
// Good
|
||||||
|
@ -487,15 +481,15 @@ _Recommendation is Electron's default_
|
||||||
If you are using [`WebViews`](web-view), you might need the pages and scripts
|
If you are using [`WebViews`](web-view), you might need the pages and scripts
|
||||||
loaded in your `<webview>` tag to open new windows. The `allowpopups` attribute
|
loaded in your `<webview>` tag to open new windows. The `allowpopups` attribute
|
||||||
enables them to create new [`BrowserWindows`](browser-window) using the
|
enables them to create new [`BrowserWindows`](browser-window) using the
|
||||||
`window.open()` method. By default, `WebViews` are not allowed to create new
|
`window.open()` method. `WebViews` are otherwise not allowed to create new
|
||||||
windows.
|
windows.
|
||||||
|
|
||||||
### Why?
|
### Why?
|
||||||
|
|
||||||
If you do not need popups, you are better off not allowing the creation of
|
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
|
new [`BrowserWindows`](browser-window) by default. This follows the principle
|
||||||
of the minimally required access: Websites that you do not know to need popups
|
of minimally required access: Don't let a website create new popups unless
|
||||||
should not have the ability to create new popups.
|
you know it needs that feature.
|
||||||
|
|
||||||
### How?
|
### How?
|
||||||
|
|
||||||
|
@ -521,7 +515,7 @@ security features.
|
||||||
### Why?
|
### Why?
|
||||||
|
|
||||||
Since WebViews live in the DOM, they can be created by a script running on your
|
Since WebViews live in the DOM, they can be created by a script running on your
|
||||||
website even if Node integration is otherwise disabled.
|
website even if Node.js integration is otherwise disabled.
|
||||||
|
|
||||||
Electron enables developers to disable various security features that control
|
Electron enables developers to disable various security features that control
|
||||||
a renderer process. In most cases, developers do not need to disable any of
|
a renderer process. In most cases, developers do not need to disable any of
|
||||||
|
@ -541,7 +535,7 @@ app.on('web-contents-created', (event, contents) => {
|
||||||
delete webPreferences.preload
|
delete webPreferences.preload
|
||||||
delete webPreferences.preloadURL
|
delete webPreferences.preloadURL
|
||||||
|
|
||||||
// Disable node integration
|
// Disable Node.js integration
|
||||||
webPreferences.nodeIntegration = false
|
webPreferences.nodeIntegration = false
|
||||||
|
|
||||||
// Verify URL being loaded
|
// Verify URL being loaded
|
||||||
|
@ -555,6 +549,6 @@ 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, it does not remove it. If your goal
|
||||||
is to display a website, a browser will be a more secure option.
|
is to display a website, a browser will be a more secure option.
|
||||||
|
|
||||||
[browser-window]: (../api/browser-window)
|
[browser-window]: ../api/browser-window.md
|
||||||
[browser-view]: (../api/browser-view)
|
[browser-view]: ../api/browser-view.md
|
||||||
[web-view]: (../api/web-view)
|
[web-view]: ../api/web-view
|
||||||
|
|
Loading…
Reference in a new issue