Electron Fuse
パッケージ時機能切り替え
Fuse とはなんでしょうか?
Electron は機能の集合体なので、アプリケーション全体に渡って特定の機能を無効化しても合理的です。 例えば、99% のアプリは ELECTRON_RUN_AS_NODE
を利用しないので、そういったアプリでその機能が利用できないバイナリを頒布できるようにしたいのです。 Electron の消費者がソースから Electron を構築することは技術的に大きな障害であり時間とお金両方のコストがかかるため、それも避けたいと考えています。
Fuse はこの問題の解決策です。高水準としては Electron バイナリ内の "マジックビット" であり、Electron アプリをパッケージングする際にそれらを反転させることで、特定の機能や制限を有効化/無効化できます。 アプリのコード署名前のパッケージ時に反転するので、OS は OS レベルのコード署名検証(Gatekeeper / App Locker) の時に反転しないようにする責任があります。
現在の Fuse
runAsNode
デフォルト: 有効
@electron/fuses: FuseV1Options.RunAsNode
runAsNode の Fuse は、 ELECTRON_RUN_AS_NODE
環境変数を尊重するかどうかを切り替えます。 この Fuse が無効になっている場合の注意として、メインプロセスの process.fork
はこの環境変数に依存して動作するため、期待通りに機能しないことがあります。 代わりに、ユーティリティプロセス を使用することを推奨します。これは、スタンドアロンの Node.js プロセス (SQLite サーバーのプロセスや同様の場合) が必要な多くのユースケースで機能します。
cookieEncryption
デフォルト: 無効
@electron/fuses: FuseV1Options.EnableCookieEncryption
cookieEncryption の Fuse は、ディスクに保存する Cookie を OS レベルの暗号化キーで暗号化するかどうかを切り替えます。 デフォルトでは、Chromium が Cookie を保存に使用する SQLite データベースは値を平文で保存します。 Chrome と同じくアプリの Cookie を暗号化するようにしたい場合は、この Fuse を有効にすべきです。 これは一方向の変更です。この Fuse を有効にすると、暗号化されていないクッキーは書き込み時に暗号化されます。しかしその後再びこの Fuse を無効にすると、Cookie ストアが事実上破損して使い物にならなくなりますので、ご注意ください。 ほとんどのアプリは安全にこの Fuse を有効化できます。
nodeOptions
デフォルト: 有効
@electron/fuses: FuseV1Options.EnableNodeOptionsEnvironmentVariable
nodeOptions の Fuse は NODE_OPTIONS
とNODE_EXTRA_CA_CERTS
の環境変数を尊重するかどうかを切り替えます。 NODE_OPTIONS
環境変数は Node.js ランタイムにあらゆる種類のカスタムオプションを渡すために利用でき、普通は本番環境のアプリでは使用されません。 ほとんどのアプリは安全にこの Fuse を無効化できます。
nodeCliInspect
デフォルト: 有効
@electron/fuses: FuseV1Options.EnableNodeCliInspectArguments
nodeCliInspect の Fuse は --inspect
、--inspect-brk
などのフラグを尊重するかどうかを切り替えます。 無 効にすると、SIGUSR1
シグナルがメインプロセスのインスペクタを初期化しないことも保証されます。 ほとんどのアプリは安全にこの Fuse を無効化できます。
embeddedAsarIntegrityValidation
デフォルト: 無効
@electron/fuses: FuseV1Options.EnableEmbeddedAsarIntegrityValidation
embeddedAsarIntegrityValidation の Fuse は、macOS の実験的機能である、読み込み時に app.asar
ファイルの内容を検証する機能を切り替えます。 この機能はパフォーマンスへの影響を最小限に抑えるように設計されていますが、 app.asar
アーカイブ内からのファイル読み込みがわずかに遅くなる可能性があります。
ASAR 整合性検査の使用方法の詳細については、Asar 整合性 のドキュメントをご参照ください。
onlyLoadAppFromAsar
デフォルト: 無効
@electron/fuses: FuseV1Options.OnlyLoadAppFromAsar
onlyLoadAppFromAsar Fuse は、Electron がアプリコードの探索に使用する探索システムを変更します。 デフォルトでは Electron は app.asar
-> app
-> default_app.asar
の順番で探索します。 この Fuse が有効な場合、探索順序は 1 つのエントリ app.asar
になるので、embeddedAsarIntegrityValidation
Fuse と組み合わせたときに非検証コードを読み込めないようにします。
loadBrowserProcessSpecificV8Snapshot
デフォルト: 無効
@electron/fuses: FuseV1Options.LoadBrowserProcessSpecificV8Snapshot
loadBrowserProcessSpecificV8Snapshot Fuse は、ブラウザープロセスに使用する V8 スナップショットファイルを変更します。 デフォルトでは、Electron のプロセスはすべて同じ V8 スナップショットファイルを使用します。 この Fuse が有効な場合、ブラウザープロセスは browser_v8_context_snapshot.bin
というファイルを V8 スナップショットに使用します。 他のプロセスは通常通りの V8 スナップショットファイルを使用します。
grantFileProtocolExtraPrivileges
デフォルト: 有効
@electron/fuses: FuseV1Options.GrantFileProtocolExtraPrivileges
grantFileProtocolExtraPrivileges Fuse は、file://
プロトコルから読み込まれたページに、従来のウェブブラウザが受ける権限を超えるような権限を付与するかどうかを変更します。 この動作はかつての Electron では Electron アプリの中核を担うものでしたが、現在はアプリが カスタムプロトコルからローカルファイルを提供する 必要があるため、もはや必要ありません。 file://
からページを提供していない場合は、この Fuse を無効にすべきです。
この Fuse によって file://
プロトコルに付与される追加の権限は、大雑把にまとめると以下のようになります。
file://
プロトコルのページがfetch
を使用してfile://
越しにその他のアセットを読み込めますfile://
プロトコルのページがサービスワーカーを使用できますfile://
プロトコルのページが、サンドボックスの設定に関係なくfile://
プロトコル上で動く子フレームにも普遍的なアクセス権限を持ちます
Fuse の反転方法は何ですか?
簡単な方法
これら Fuse を簡単に反転させるために、便利なモジュール @electron/fuses
を作成しました。 使用方法や潜在的なエラーケースといった詳細 は、このモジュールの README を確認してください。
const { flipFuses, FuseVersion, FuseV1Options } = require('@electron/fuses')
flipFuses(
// electron へのパス
require('electron'),
// 反転する Fuse
{
version: FuseVersion.V1,
[FuseV1Options.RunAsNode]: false
}
)
Fuses CLI を使用すると、Fuse が反転したことの検証や、任意の Electron アプリの Fuse の状態を確認できます。
npx @electron/fuses read --app /Applications/Foo.app
難しい方法
簡易用語集
- Fuse Wire: Fuse の制御に使用する Electron バイナリ内のバイト列
- Sentinel: Fuse Wire の位置特定に使用できる静的な既知のバイト列
- Fuse Schema: Fuse Wire が許容する値の形式
手動で Fuse を反転させるには、Electron バイナリを編集し必要な Fuse の状態を表すバイト列になるように Fuse Wire を修正する必要があります。
Electron バイナリのどこかに、以下のようなバイト列があります。
| ...binary | sentinel_bytes | fuse_version | fuse_wire_length | fuse_wire | ...binary |
sentinel_bytes
は厳密にこのような文字列dL7pKGdnNz796PbbjQWNKmHXBZaB9tsX
ですfuse_version
は単一バイトで、その符号無し整数の値が Fuse Schema のバージョンを表します。fuse_wire_length
は単一バイトで、その符号無し整数の値は後続の Fuse Wire にある Fuse の数を表します。fuse_wire
は N バイトのシーケンスで、各バイトは 1 つの Fuse とその状態を表します。- "0" (0x30) は無効な Fuse を表します
- "1" (0x31) は有効な Fuse を表します
- "r" (0x72) は削除された Fuse を表し、このバイトを 1 や 0 に変更しても効果はありません。
Fuse を反転させるには、Fuse Wire の位置を見つけ、状態に応じて "0" または "1" に変更します。
現在のスキーマは こちら で閲覧できます。