こんにちは。プレイドのRyosukeです。現在、明治大学総合数理学部現象数理学科3年生で統計学系の研究室にいます。
今回は、Electron Webviewのセキュリティ面で注意すべきことを書きます。
Electron
Electronとはweb techでクロスプラットフォームデスクトップアプリを作ることができるものです。どういうアプリがElectronで作られてるのかはAwesome electronを御覧ください。
Electronは、nodejsをバックで動かし、chromiumブラウザ上でウェブページを表示することでデスクトップアプリを表現しています。Electronでは、nodejs側のjsプロセス(メインプロセス)とブラウザ側のjsプロセス(レンダラープロセス)は別になるため、プロセス間の通信手段としてipc
(internal procedure call?)を使用します。
また、ブラウザ側では<webview>
というhtmlタグを使用することができます。webview
とはiframeのように別のwebページをurlを指定することで表示するものです。ただ、iframeと違う部分があり、それは、webview内のjsプロセスはブラウザのjsプロセスとは別のインスタンスをもつということです。もちろん、webview内のjsプロセスはブラウザと同様にレンダラープロセスなので、メインプロセスとの通信手段を持ちます。ここに、セキュリティ面で注意すべきことがあります。
Webviewのセキュリティ
webviewのレンダラープロセスとメインプロセス間で通信をする必要がないのであれば問題はありませんが、それをしたかったり、webviewのレンダラープロセスでnodejsのAPIをrequireして使用したい場合はセキュリティ面で注意が必要です。
安全じゃない方法 - nodeintegration
<webview>
のアトリビュートにはnodeintegration
というものがあります。これは、デフォルトではfalseになっていますが、明示的に指定することで、webview内でnodejsのrequireやprocessといった低レベルなシステムへのアクセスが許されます。webviewとメインプロセス間の通信にはipc
をrequireする必要があるので、それをしたいのであれば、webviewにnodeintegration
をつけるのが手っ取り早いです。
しかし、XSSの危険性があり悪意のあるサイトが色々と悪さをできてしまいます。ですので、必ずnodeintegration
がfalse
になっていることを__確認__してください。
安全な方法 - preload
では、どうすればwebview内でipcや他のapiを使うことができるのでしょう。実はpreload
アトリビュートにjsファイルパスを指定することで、そのjsをpreloadすることができます。また、そのpreloadされるjsには制限が無いのでrequireをすることができますし、preload内のスコープはセキュリティ上、webview内のスコープとは別になるので、ある程度は安心できます。このpreloadを上手く使用することで、nodeintegration
がfalseなwebview内でも使用したいnodejs apiを使用できます。
<webview preload="PATH/TO/PREALOD_JS" src="URL">
const {ipcRenderer} = require('electron')
global.sendToHost = (message) => {
ipcRenderer.sendToHost(message)
}