プロセスのサンドボックス化
Chromium の重要なセキュリティ機能の一つは、プロセスをサンドボックス内で実行できることです。 サンドボックスは、ほとんどのシステムリソースへのアクセスを制限することで悪意のあるコードが引き起こす被害を制限します。サンドボックスのプロセスは、CPU サイクルとメモリのみを自由に使用できます。 サンドボックス化したプロセスで追加の特権を必要とする操作を実行するには、専用の通信チャンネルを使用してより特権のあるプロセスにタスクを委譲します。
Chromium では、メインプロセス以外のほとんどのプロセスにサンドボックス化が適用されます。 これにはレンダラープロセスのほか、オーディオサービス、GPU サービス、ネットワークサービスなどのユーティリティプロセスも含まれます。
詳しい情報は Chromium の サンドボックスデザインのドキュメント をご参照ください。
Electron 20 から、サンドボックスは追加設定なしでレンダラープロセスに対して有効です。 プロセスのサンドボックスを無効化する場合は、単一のプロセスでのサンドボックス無効化 の節をご参照ください。
Electron でのサンドボックスの動作
Electron のサンドボックス化したプロセスは ほぼ Chromium と同じように動作しますが、Electron は Node.js とのインターフェイスであるために更に考慮すべき概念がいくつかあります。
レンダラープロセス
Electron のレンダラープロセスをサンドボックス化すると、通常の Chrome レンダラーと同じように動作します。 サンドボックス化したレンダラーは Node.js 環境が初期化されません。
そのため、サンドボックスを有効にすると、レンダラープロセスはプロセス間通信 (IPC) を介したメインプロセスへのタスクの委譲によってのみ、特権的なタスク (ファイルシステムとのやりとり、システムへの変更、サブプロセスの生成など) を実行できます。
For more info on inter-process communication, check out our IPC guide.
プリロードスクリプト
レンダラープロセスがメインプロセスと通信できるようにするため、サンドボックス化したレンダラーにアタッチされるプリロードスクリプトでは 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 のようなバンドラーを使用してください。
Note that because the environment presented to the preload
script is substantially more privileged than that of a sandboxed renderer, it is still possible to leak privileged APIs to untrusted code running in the renderer process unless contextIsolation
is enabled.
サンドボックスの設定
ほとんどのアプリでは、サンドボックス化が最良の選択です。 サンドボックスと互換性のない特定のユースケース (例えば、レンダラーでネイティブ Node モジュールを使用する場合) であれば、特定のプロセスに対してサンドボックスを無効化できます。 これは信頼できないコードやコンテンツがサンドボックス化されていないプロセスに存在する場合では特に、セキュリティ上のリスクを招きます。
単一のプロセスでサンドボックスを無効化する
In Electron, renderer sandboxing can be disabled on a per-process basis with the sandbox: false
preference in the BrowserWindow
constructor.
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')
})
アプリ全体でサンドボックスを有効にする
If you want to force sandboxing for all renderers, you can also use the 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 のサンドボックスを無効にする (テストのみ)
You can also disable Chromium's sandbox entirely with the --no-sandbox
CLI flag, which will disable the sandbox for all processes (including utility processes). このフラグはテスト目的でのみ使用し、本番環境では 絶対に 使用しないことを強く推奨します。
注意として、この状況で sandbox: true
オプションを指定してもレンダラーの Node.js 環境は無効になります。
信頼されないコンテンツの描画に関する注意
信頼されないコンテンツを Electron で描画することはまだ未知の領域ですが、いくつかのアプリケーションは成功を収めています (例: Beaker Browser)。 私たちの目標はサンドボックス化したコンテンツのセキュリティに関して Chrome にできるだけ近づくことですが、突き詰めるといくつかの基本的な問題のためにいつも後れを取ることになります。
- 私たちには Chromium 製品に適したセキュリティのリソースやノウハウがありません。 今あるものを活かして Chromium からできることはすべて継承し、セキュリティ上の問題にも迅速に対応できるようにしていますが、Electron は Chromium のようにリソースを割くことができず、Chromium のようなセキュリティは確保できません。
- Chrome のセキュリティ機能 (セーフブラウジングや証明書の透過性など) の中には、中央集権化と専用サーバが必要なものがありますが、どちらも Electron プロジェクトの目的に反しています。 そのため、セキュリティ関連のコストが発生しないように、Electron では機能を無効にしています。
- Chromium は 1 つだけですが Electron には何千ものアプリが存在しており、それぞれのアプリの動作は微妙に異なります。 これらの違いを考慮すると巨大な可能性の空間が生じ、通常とは異なるユースケースでのプラットフォームのセキュリティ確保に挑戦することになります。
- セキュリティアップデートをユーザーに直接伝えることができないため、セキュリティアップデートをユーザーに届けるために、アプリベンダーに Electron のバージョンをアップグレードして頂いています。
Chromium のセキュリティ修正を古いバージョンの Electron にバックポートするよう最善の努力をしていますが、すべての修正のバックポートは保証できません。 堅牢性を確保するには、Electron の最新の安定版を使用することが最善の方法です。