プロセスのサンドボックス化
Chromium の重要なセキュリティ機能の一つは、プロセスをサンドボックス内で実行できることです。 サンドボックスは、ほとんどのシステムリソースへのアクセスを制限することで悪意のあるコードが引き起こす被害を制限します。サンドボックスのプロセスは、CPU サイクルとメモリのみを自由に使用できます。 サンドボックス化したプロセスで追加の特権を必要とする操作を実行するには、専用の通信チャンネルを使用してより特権のあるプロセスにタスクを委譲します。
Chromium では、メインプロセス以外のほとんどのプロセスにサンドボックス化が適用されます。 これにはレンダラープロセスのほか、オーディオサービス、GPU サービス、ネットワークサービスなどのユーティリティプロセスも含まれます。
詳しい情報は Chromium の サンドボックスデザインのドキュメント をご参照ください。
Electron 20 から、サンドボックスは追加設定なしでレンダラープロセスに対して有効です。 プロセスのサンドボックスを無効化する場合は、単一のプロセスでのサンドボックス無効化 の節をご参照ください。
Electron でのサンドボックスの動作
Electron のサンドボックス化したプロセスは ほぼ Chromium と同じように動作しますが、Electron は Node.js とのインターフェイスであるために更に考慮すべき概念がいくつかあります。
レンダラープロセス
Electron のレンダラープロセスをサンドボックス化すると、通常の Chrome レンダラーと同じように動作します。 サンドボックス化したレンダラーは Node.js 環境が初期化されません。
そのため、サンドボックスを有効にすると、レンダラープロセスはプロセス間通信 (IPC) を介したメインプロセスへのタスクの委譲によってのみ、特権的なタスク (ファイルシステムとのやりとり、システムへの変更、サブプロセスの生成など) を実行できます。
プロセス間通信に関する詳細は、IPC ガイド をご確認ください。
プリロードスクリプト
レンダラープロセスがメインプロセスと通信できるようにするため、サンドボックス化したレンダラーにアタッチされるプリロードスクリプトでは Node.js API をポリフィルしたサブセットを利用できるようになっています。 Node の require
に似た require
関数のモジュールを公開してありますが、これは以下 Electron や Node の組み込みモジュールのサブセットしかインポートできません。
electron
(次のレンダラープロセスモジュール:contextBridge
,crashReporter
,ipcRenderer
,nativeImage
,webFrame
,webUtils
)events
timers
url
node: インポート は以下のものをサポートしています。
加えて、プリロードスクリプトは以下の Node.js プリミティブもグローバルとしてポリフィルします。
require
関数は機能を限定したポリフィルであるため、CommonJS モジュール を利用したプリロードスクリプトの複数ファイル分割ができません。 プリロードコードを分割する必要がある場合は、webpack や Parcel のようなバンドラーを使用してください。
preload
スクリプトに与えられる環境は、サンドボックス化したレンダラーの環境よりも大幅に特権的です。contextIsolation
が有効になっていない限り、特権的な API をレンダラープロセスで実行している信頼されていないコードにリークできることに注意してください。
サンドボックスの設定
ほとんどのアプリでは、サンドボックス化が最良の選択です。 サ ンドボックスと互換性のない特定のユースケース (例えば、レンダラーでネイティブ Node モジュールを使用する場合) であれば、特定のプロセスに対してサンドボックスを無効化できます。 これは信頼できないコードやコンテンツがサンドボックス化されていないプロセスに存在する場合では特に、セキュリティ上のリスクを招きます。
単一のプロセスでサンドボックスを無効化する
Electron では、BrowserWindow
コンストラクタで sandbox: false
を設定することでレンダラープロセスごとにサンドボックスを無効化できます。
app.whenReady().then(() => {
const win = new BrowserWindow({
webPreferences: {
sandbox: false
}
})
win.loadURL('https://google.com')
})
レンダラーで Node.js インテグレーションが有効の場合は、サンドボックス化も無効です。 これは BrowserWindow コンストラクタで nodeIntegration: true
フラグを付けるとできます。
app.whenReady().then(() => {
const win = new BrowserWindow({
webPreferences: {
nodeIntegration: true
}
})
win.loadURL('https://google.com')
})
アプリ全体でサンドボックスを有効にする
すべてのレンダラーにサンドボックスを強制したい場合は、app.enableSandbox
API も利用できます。 注意として、この API は app の ready
イベントより前に呼ぶ必要があります。
app.enableSandbox()
app.whenReady().then(() => {
// `app.enableSandbox()` が呼び出されたので任意の sandbox:false 呼び出しはオーバーライドされます。
const win = new BrowserWindow()
win.loadURL('https://google.com')
})
Chromium のサンドボックスを無効にする (テストのみ)
--no-sandbox
CLI フラグで Chromium のサンドボックスを完全に無効化することもできます。これは、(ユーティリティプロセスを含む) すべてのプロセスのサンドボックスを無効化します。 このフラグはテスト目的でのみ使用し、本番環境では 絶対に 使用しないことを強く推奨します。
注意として、この状況で sandbox: true
オプションを指定してもレンダラーの Node.js 環境は無効になります。