メインコンテンツへ飛ぶ

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 はこの環境変数に依存して動作するため、期待通りに機能しないことがあります。 Instead, we recommend that you use Utility Processes, which work for many use cases where you need a standalone Node.js process (like a Sqlite server process or similar scenarios).

cookieEncryption

既定: 無効 @electron/fuses: FuseV1Options.EnableCookieEncryption

cookieEncryption の Fuse は、ディスクに保存する Cookie を OS レベルの暗号化キーで暗号化するかどうかを切り替えます。 デフォルトでは、Chromium が Cookie を保存に使用する SQLite データベースは値を平文で保存します。 Chrome と同じくアプリの Cookie を暗号化するようにしたい場合は、この Fuse を有効にすべきです。 これは一方向の変更です。この Fuse を有効にすると、暗号化されていないクッキーは書き込み時に暗号化されます。しかしその後再びこの Fuse を無効にすると、Cookie ストアが事実上破損して使い物にならなくなりますので、ご注意ください。 ほとんどのアプリは安全にこの Fuse を有効化できます。

nodeOptions

既定: 有効 @electron/fuses: FuseV1Options.EnableNodeOptionsEnvironmentVariable

The nodeOptions fuse toggles whether the NODE_OPTIONS and NODE_EXTRA_CA_CERTS environment variables are respected. The NODE_OPTIONS environment variable can be used to pass all kinds of custom options to the Node.js runtime and isn't typically used by apps in production. ほとんどのアプリは安全にこの 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

The grantFileProtocolExtraPrivileges fuse changes whether pages loaded from the file:// protocol are given privileges beyond what they would receive in a traditional web browser. This behavior was core to Electron apps in original versions of Electron but is no longer required as apps should be serving local files from custom protocols now instead. If you aren't serving pages from file:// you should disable this fuse.

The extra privileges granted to the file:// protocol by this fuse are incompletely documented below:

  • file:// protocol pages can use fetch to load other assets over file://
  • file:// protocol pages can use service workers
  • file:// protocol pages have universal access granted to child frames also running on file:// protocols regardless of sandbox settings

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" に変更します。

現在のスキーマは こちら で閲覧できます。