@@ -81,7 +81,8 @@ improve the security of your application.
818110 . [ Do not use ` enableBlinkFeatures ` ] ( #10-do-not-use-enableblinkfeatures )
828211 . [ ` <webview> ` : Do not use ` allowpopups ` ] ( #11-do-not-use-allowpopups )
838312 . [ ` <webview> ` : Verify options and params] ( #12-verify-webview-options-before-creation )
84-
84+ 13 . [ Disable or limit navigation] ( #13-disable-or-limit-navigation )
85+ 14 . [ Disable or limit creation of new windows] ( #13-disable-or-limit-creation-of-new-windows )
8586
8687## 1) Only Load Secure Content
8788
@@ -557,7 +558,7 @@ for newly created [`<webview>`][webview-tag] tags.
557558
558559Before a [ ` <webview> ` ] [ webview-tag ] tag is attached, Electron will fire the
559560` will-attach-webview ` event on the hosting ` webContents ` . Use the event to
560- prevent the creation of webviews with possibly insecure options.
561+ prevent the creation of ` webViews ` with possibly insecure options.
561562
562563``` js
563564app .on (' web-contents-created' , (event , contents ) => {
@@ -580,6 +581,93 @@ app.on('web-contents-created', (event, contents) => {
580581Again, this list merely minimizes the risk, it does not remove it. If your goal
581582is to display a website, a browser will be a more secure option.
582583
584+ ## 13) Disable or limit navigation
585+
586+ If your app has no need to navigate or only needs to navigate to known pages,
587+ it is a good idea to limit navigation outright to that known scope, disallowing
588+ any other kinds of navigation.
589+
590+ ### Why?
591+
592+ Navigation is a common attack vector. If an attacker can convince your app to
593+ navigate away from its current page, they can possibly force your app to open
594+ web sites on the Internet. Even if your ` webContents ` are configured to be more
595+ secure (like having ` nodeIntegration ` disabled or ` contextIsolation ` enabled),
596+ getting your app to open a random web site will make the work of exploiting your
597+ app a lot easier.
598+
599+ A common attack pattern is that the attacker convinces your app's users to
600+ interact with the app in such a way that it navigates to one of the attacker's
601+ pages. This is usually done via links, plugins, or other user-generated content.
602+
603+ ### How?
604+
605+ If your app has no need for navigation, you can call ` event.preventDefault() `
606+ in a [ ` will-navigate ` ] [ will-navigate ] handler. If you know which pages your app
607+ might navigate to, check the URL in the event handler and only let navigation
608+ occur if it matches the URLs you're expecting.
609+
610+ We recommend that you use Node's parser for URLs. Simple string comparisons can
611+ sometimes be fooled - a ` startsWith('https://google.com') ` test would let
612+ ` https://google.com.attacker.com ` through.
613+
614+ ``` js
615+ const URL = require (' url' )
616+
617+ app .on (' web-contents-created' , (event , contents ) => {
618+ contents .on (' will-navigate' , (event , navigationUrl ) => {
619+ const parsedUrl = new URL (navigationUrl)
620+
621+ if (url .hostname !== ' my-own-server.com' ) {
622+ event .preventDefault ()
623+ }
624+ })
625+ })
626+ ```
627+
628+ ## 14) Disable or limit creation of new windows
629+
630+ If you have a known set of windows, it's a good idea to limit the creation of
631+ additional windows in your app.
632+
633+ ### Why?
634+
635+ Much like navigation, the creation of new ` webContents ` is a common attack
636+ vector. Attackers attempt to convince your app to create new windows, frames,
637+ or other renderer processes with more privileges than they had before; or
638+ with pages opened that they couldn't open before.
639+
640+ If you have no need to create windows in addition to the ones you know you'll
641+ need to create, disabling the creation buys you a little bit of extra
642+ security at no cost. This is commonly the case for apps that open one
643+ ` BrowserWindow ` and do not need to open an arbitrary number of additional
644+ windows at runtime.
645+
646+ ### How?
647+
648+ [ ` webContents ` ] [ web-contents ] will emit the [ ` new-window ` ] [ new-window ] event
649+ before creating new windows. That event will be passed, amongst other
650+ parameters, the ` url ` the window was requested to open and the options used to
651+ create it. We recommend that you use the event to scrutinize the creation of
652+ windows, limiting it to only what you need.
653+
654+ ``` js
655+ const { shell } = require (' electron' )
656+
657+ app .on (' web-contents-created' , (event , contents ) => {
658+ contents .on (' new-window' , (event , navigationUrl ) => {
659+ // In this example, we'll ask the operating system
660+ // to open this event's url in the default browser.
661+ event .preventDefault ()
662+
663+ shell .openExternal (navigationUrl)
664+ })
665+ })
666+ ```
667+
583668[ browser-window ] : ../api/browser-window.md
584669[ browser-view ] : ../api/browser-view.md
585670[ webview-tag ] : ../api/webview-tag.md
671+ [ web-contents ] : ../api/web-contents.md
672+ [ new-window ] : ../api/web-contents#event-new-window
673+ [ will-navigate ] : ../api/web-contents#event-will-navigate
0 commit comments