📝 Verify WebView creation
This commit is contained in:
parent
d67c64b6fa
commit
f790c24c27
1 changed files with 54 additions and 32 deletions
|
@ -77,26 +77,7 @@ This is not bulletproof, but at the least, you should attempt the following:
|
||||||
* WebViews: Do not use `disablewebsecurity`
|
* WebViews: Do not use `disablewebsecurity`
|
||||||
* WebViews: Do not use `allowpopups`
|
* WebViews: Do not use `allowpopups`
|
||||||
* WebViews: Do not use `insertCSS` or `executeJavaScript` with remote CSS/JS.
|
* WebViews: Do not use `insertCSS` or `executeJavaScript` with remote CSS/JS.
|
||||||
* WebViews: Verify the options and params of all `<webview>` tags before they
|
* [WebViews: Verify the options and params of all `<webview>` tags](#verify-webview-options-before-creation)
|
||||||
get attached using the `will-attach-webview` event:
|
|
||||||
|
|
||||||
```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
|
|
||||||
|
|
||||||
// Disable node integration
|
|
||||||
webPreferences.nodeIntegration = false
|
|
||||||
|
|
||||||
// Verify URL being loaded
|
|
||||||
if (!params.src.startsWith('https://yourapp.com/')) {
|
|
||||||
event.preventDefault()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
## Only Display Secure Content
|
## Only Display Secure Content
|
||||||
Any resources not included with your application should be loaded using a secure
|
Any resources not included with your application should be loaded using a secure
|
||||||
|
@ -139,24 +120,25 @@ browserWindow.loadURL('https://my-website.com')
|
||||||
|
|
||||||
## Disable Node Integration for Remote Content
|
## Disable Node Integration for Remote Content
|
||||||
It is paramount that you disable Node integration in any renderer (`BrowserWindow`,
|
It is paramount that you disable Node integration in any renderer (`BrowserWindow`,
|
||||||
`BrowserView`, `WebView`) that loads remote content. The goal of disabling Node
|
`BrowserView`, or `WebView`) that loads remote content. The goal of disabling Node
|
||||||
integration is to limit the powers you grant to remote content, thus making it
|
integration is to limit the powers you grant to remote content, thus making it
|
||||||
dramatically more difficult for an attacker to harm your users should they gain
|
dramatically more difficult for an attacker to harm your users should they gain
|
||||||
control over your website.
|
the ability to execute JavaScript on your website.
|
||||||
|
|
||||||
Disabling Node integration does not mean that you cannot grant additional powers
|
Disabling Node integration does not mean that you cannot grant additional powers
|
||||||
to the website you are loading – if you are opening a `BrowserWindow` pointed at
|
to the website you are loading. If you are opening a `BrowserWindow` pointed at
|
||||||
`https://my-website.com`, the goal is to give that website exactly the ability it
|
`https://my-website.com`, the goal is to give that website exactly the abilities
|
||||||
needs, but no more.
|
it needs, but no more.
|
||||||
|
|
||||||
### Why?
|
### Why?
|
||||||
A cross-site-scripting (XSS) becomes dramatically more dangerous if an attacker
|
A cross-site-scripting (XSS) attack becomes dramatically more dangerous if an
|
||||||
can jump out of the renderer process and execute code on the user's computer.
|
attacker can jump out of the renderer process and execute code on the user's
|
||||||
Cross-site-scripting attacks are fairly common - and while an issue, their power
|
computer. Cross-site-scripting attacks are fairly common - and while an issue,
|
||||||
is usually limited to messing with the website that they are executed on. However,
|
their power is usually limited to messing with the website that they are executed
|
||||||
in a renderer process with Node integration enabled, an XSS attack becomes a whole
|
on. However, in a renderer process with Node.js integration enabled, an XSS attack
|
||||||
different class of threat vector: A so-called "Remote Code Execution" (RCE) attack.
|
becomes a whole different class of attack: A so-called "Remote Code Execution"
|
||||||
Disabling Node.js integration limits the power of successful XSS attacks.
|
(RCE) attack. Disabling Node.js integration limits the power of successful XSS
|
||||||
|
attacks.
|
||||||
|
|
||||||
### How?
|
### How?
|
||||||
```js
|
```js
|
||||||
|
@ -192,5 +174,45 @@ window.readConfig = function () {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## 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
|
||||||
|
always create an independent renderer process with its own `webPreferences`.
|
||||||
|
|
||||||
|
It is a good idea to control the creation of new `WebViews` from the main process
|
||||||
|
and to verify that their webPreferences do not disable security features.
|
||||||
|
|
||||||
|
### Why?
|
||||||
|
Since WebViews live in the DOM, they can be created by a script running on your
|
||||||
|
website even if Node integration is otherwise disabled.
|
||||||
|
|
||||||
|
Electron enables developers to disable various security features that control
|
||||||
|
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>` tags.
|
||||||
|
|
||||||
|
### How?
|
||||||
|
Before a `<WebView>` 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
|
||||||
|
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
|
||||||
|
|
||||||
|
// Disable node integration
|
||||||
|
webPreferences.nodeIntegration = false
|
||||||
|
|
||||||
|
// Verify URL being loaded
|
||||||
|
if (!params.src.startsWith('https://yourapp.com/')) {
|
||||||
|
event.preventDefault()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
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.
|
||||||
|
|
Loading…
Reference in a new issue