プロセスサンドボックス
Chromium の重要なセキュリティ機能の 1 つは、プロセスをサンドボックス内で実行できることです。サンドボックスは、ほとんどのシステムリソースへのアクセスを制限することで、悪意のあるコードが引き起こす可能性のある損害を制限します。サンドボックス化されたプロセスは、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をリークすることが依然として可能であることに注意してください。
サンドボックスの設定
ほとんどのアプリでは、サンドボックス化が最適な選択肢です。サンドボックスと互換性のない特定のユースケース(たとえば、レンダラーでネイティブノードモジュールを使用する場合)では、特定のプロセスのサンドボックスを無効にすることができます。これは、特にサンドボックス化されていないプロセスに信頼できないコードやコンテンツが存在する場合、セキュリティリスクを伴います。
単一のプロセスのサンドボックスを無効にする
Electronでは、レンダラーのサンドボックス化は、BrowserWindow
コンストラクターでsandbox: false
プリファレンスを使用することで、プロセスごとに無効にできます。
app.whenReady().then(() => {
const win = new BrowserWindow({
webPreferences: {
sandbox: false
}
})
win.loadURL('https://google.com')
})
レンダラーでNode.js統合が有効になっている場合も、サンドボックス化は無効になります。これは、nodeIntegration: true
フラグを使用してBrowserWindowコンストラクターで行うことができます。
app.whenReady().then(() => {
const win = new BrowserWindow({
webPreferences: {
nodeIntegration: true
}
})
win.loadURL('https://google.com')
})
サンドボックスをグローバルに有効にする
すべてのレンダラーでサンドボックス化を強制する場合は、app.enableSandbox
APIを使用することもできます。このAPIは、アプリのready
イベントの前に呼び出す必要があることに注意してください。
app.enableSandbox()
app.whenReady().then(() => {
// any sandbox:false calls are overridden since `app.enableSandbox()` was called.
const win = new BrowserWindow()
win.loadURL('https://google.com')
})
Chromiumのサンドボックスを無効にする(テストのみ)
また、--no-sandbox
CLIフラグを使用してChromiumのサンドボックスを完全に無効にすることもできます。これにより、すべてのプロセス(ユーティリティプロセスを含む)のサンドボックスが無効になります。このフラグはテスト目的にのみ使用し、本番環境では決して使用しないことを強くお勧めします。
sandbox: true
オプションは、レンダラーのNode.js環境を無効にすることにも注意してください。
信頼できないコンテンツのレンダリングに関する注意
Electronで信頼できないコンテンツをレンダリングすることは、まだ多少未知の領域ですが、一部のアプリは成功を収めています(例:Beaker Browser)。私たちの目標は、サンドボックス化されたコンテンツのセキュリティに関して可能な限りChromeに近づけることですが、いくつかの根本的な問題のために、最終的には常に後れを取ることになります。
- Chromiumが製品のセキュリティに適用する専任のリソースや専門知識はありません。私たちは、手持ちのものを最大限に活用し、Chromiumからできる限りのものを継承し、セキュリティ問題に迅速に対応するために最善を尽くしていますが、Chromiumが専用できるリソースなしでは、ElectronはChromiumほど安全にはなり得ません。
- Chromeのセキュリティ機能(セーフブラウジングや証明書透過性など)の中には、中央集権的な機関と専用サーバーを必要とするものがあり、どちらもElectronプロジェクトの目標に反します。そのため、Electronではこれらの機能を無効にしています。その結果、本来であれば得られたはずの関連するセキュリティを犠牲にしています。
- Chromiumは1つしかありませんが、Electron上に構築されたアプリは何千もあり、そのすべてがわずかに異なる動作をします。それらの違いを考慮すると、膨大な可能性のスペースが生じ、異常なユースケースでプラットフォームのセキュリティを確保することが困難になる可能性があります。
- セキュリティアップデートをユーザーに直接プッシュすることはできないため、セキュリティアップデートがユーザーに届くためには、アプリのベンダーがアプリの基盤となるElectronのバージョンをアップグレードすることに頼っています。
Chromiumのセキュリティ修正を古いバージョンのElectronにバックポートするために最善を尽くしますが、すべての修正がバックポートされることを保証するものではありません。安全を保つための最善の策は、最新の安定版のElectronを使用することです。