跳到主要内容

Electron 保险丝

打包时功能切换

什么是保险丝?

对于 Electron 的一部分功能,禁用整个应用程序的某些功能是有意义的。例如,99% 的应用程序不使用 ELECTRON_RUN_AS_NODE,这些应用程序希望能够发布一个无法使用该功能的二进制文件。我们也不希望 Electron 用户从源代码构建 Electron,因为这既是一项巨大的技术挑战,又需要付出大量的时间和金钱成本。

保险丝是解决此问题的方法,从高层次上讲,它们是 Electron 二进制文件中的“魔术位”,可以在打包 Electron 应用程序时翻转,以启用/禁用某些功能/限制。因为它们是在代码签名应用程序之前在打包时翻转的,所以操作系统负责确保这些位不会通过操作系统级别的代码签名验证(Gatekeeper/App Locker)翻转回来。

当前保险丝

runAsNode

默认:已启用

@electron/fuses: FuseV1Options.RunAsNode

runAsNode 保险丝切换是否遵守 ELECTRON_RUN_AS_NODE 环境变量。请注意,如果禁用此保险丝,则主进程中的 process.fork 将无法按预期工作,因为它依赖此环境变量才能工作。相反,我们建议您使用 Utility Processes,它适用于许多需要独立的 Node.js 进程(例如 Sqlite 服务器进程或类似场景)的用例。

cookieEncryption

默认:已禁用

@electron/fuses: FuseV1Options.EnableCookieEncryption

cookieEncryption 保险丝切换是否使用操作系统级别的加密密钥加密磁盘上的 cookie 存储。默认情况下,Chromium 用于存储 cookie 的 sqlite 数据库以纯文本形式存储这些值。如果您希望确保您的应用程序 cookie 以与 Chrome 相同的方式加密,则应启用此保险丝。请注意,这是一个单向转换,如果您启用此保险丝,现有的未加密 cookie 将在写入时加密,但如果您再次禁用该保险丝,则您的 cookie 存储将实际上损坏且无用。大多数应用程序可以安全地启用此保险丝。

nodeOptions

默认:已启用

@electron/fuses: FuseV1Options.EnableNodeOptionsEnvironmentVariable

nodeOptions 保险丝切换是否遵守 NODE_OPTIONSNODE_EXTRA_CA_CERTS 环境变量。NODE_OPTIONS 环境变量可用于将各种自定义选项传递给 Node.js 运行时,并且通常不用于生产中的应用程序。大多数应用程序可以安全地禁用此保险丝。

nodeCliInspect

默认:已启用

@electron/fuses: FuseV1Options.EnableNodeCliInspectArguments

nodeCliInspect 保险丝切换是否遵守 --inspect--inspect-brk 等标志。禁用时,它还确保 SIGUSR1 信号不会初始化主进程检查器。大多数应用程序可以安全地禁用此保险丝。

embeddedAsarIntegrityValidation

默认:已禁用

@electron/fuses: FuseV1Options.EnableEmbeddedAsarIntegrityValidation

embeddedAsarIntegrityValidation 保险丝切换 macOS 上的一个实验性功能,该功能在加载时验证 app.asar 文件的内容。此功能旨在最大限度地减少性能影响,但可能会稍微减慢从 app.asar 存档内部读取文件的速度。

有关如何使用 asar 完整性验证的更多信息,请阅读 Asar 完整性 文档。

onlyLoadAppFromAsar

默认:已禁用

@electron/fuses: FuseV1Options.OnlyLoadAppFromAsar

onlyLoadAppFromAsar 保险丝更改 Electron 用于查找应用程序代码的搜索系统。默认情况下,Electron 将按以下顺序搜索 app.asar -> app -> default_app.asar。启用此保险丝后,搜索顺序将变为单个条目 app.asar,从而确保与 embeddedAsarIntegrityValidation 保险丝结合使用时,无法加载未经验证的代码。

loadBrowserProcessSpecificV8Snapshot

默认:已禁用

@electron/fuses: FuseV1Options.LoadBrowserProcessSpecificV8Snapshot

loadBrowserProcessSpecificV8Snapshot 保险丝更改浏览器进程使用的 V8 快照文件。默认情况下,Electron 的所有进程都将使用相同的 V8 快照文件。启用此保险丝后,浏览器进程将使用名为 browser_v8_context_snapshot.bin 的文件作为其 V8 快照。其他进程将使用它们通常使用的 V8 快照文件。

V8 快照可用于提高应用程序启动性能。V8 允许您拍摄已初始化堆的快照,然后将其加载回去以避免初始化堆的成本。

为渲染器进程和主进程使用单独的快照可以提高安全性,尤其是确保渲染器不使用启用了 nodeIntegration 的快照。有关详细信息,请参见 #35170

grantFileProtocolExtraPrivileges

默认:已启用

@electron/fuses: FuseV1Options.GrantFileProtocolExtraPrivileges

grantFileProtocolExtraPrivileges 保险丝更改是否为从 file:// 协议加载的页面提供超出传统 Web 浏览器中接收到的特权。此行为是 Electron 原始版本中 Electron 应用程序的核心,但不再需要,因为应用程序现在应该 从自定义协议提供本地文件。如果您不是从 file:// 提供页面,则应禁用此保险丝。

此保险丝授予 file:// 协议的额外特权在下面未完全记录

  • file:// 协议页面可以使用 fetch 通过 file:// 加载其他资产
  • file:// 协议页面可以使用 Service Workers
  • 无论沙盒设置如何,file:// 协议页面都具有授予也运行在 file:// 协议上的子框架的通用访问权限

如何翻转保险丝?

简单的方法

我们制作了一个方便的模块 @electron/fuses,使翻转这些保险丝变得容易。请查看该模块的 README,以获取有关用法和潜在错误情况的更多详细信息。

const { flipFuses, FuseVersion, FuseV1Options } = require('@electron/fuses')

flipFuses(
// Path to electron
require('electron'),
// Fuses to flip
{
version: FuseVersion.V1,
[FuseV1Options.RunAsNode]: false
}
)

您可以使用 fuses CLI 验证保险丝是否已翻转或检查任意 Electron 应用程序的保险丝状态。

npx @electron/fuses read --app /Applications/Foo.app

困难的方法

快速词汇表

  • 保险丝线:Electron 二进制文件中用于控制保险丝的字节序列
  • 哨兵:一个静态的已知字节序列,可用于定位保险丝线
  • 保险丝模式:保险丝线的格式/允许值

手动翻转保险丝需要编辑 Electron 二进制文件并将保险丝线修改为表示所需保险丝状态的字节序列。

在 Electron 二进制文件的某个位置,将有一个类似于以下的字节序列

| ...binary | sentinel_bytes | fuse_version | fuse_wire_length | fuse_wire | ...binary |
  • sentinel_bytes 始终是这个确切的字符串 dL7pKGdnNz796PbbjQWNKmHXBZaB9tsX
  • fuse_version 是一个单字节,其无符号整数值表示熔断器架构的版本
  • fuse_wire_length 是一个单字节,其无符号整数值表示以下熔断器导线中的熔断器数量
  • fuse_wire 是一个 N 字节的序列,每个字节代表一个熔断器及其状态。
    • "0" (0x30) 表示熔断器已禁用
    • "1" (0x31) 表示熔断器已启用
    • "r" (0x72) 表示熔断器已被移除,将字节更改为 1 或 0 都不会有任何效果。

要翻转熔断器,请在熔断器导线中找到其位置,并根据您想要的状态将其更改为 "0" 或 "1"。

您可以在此处查看当前架构。