Skip to main content

Electron Fuses

打包时间功能切换

¥Package time feature toggles

fuses 是什么?

¥What are fuses?

对于 Electron 功能的子集,禁用整个应用的某些功能是有意义的。例如,99% 的应用不使用 ELECTRON_RUN_AS_NODE,这些应用希望能够发布无法使用该功能的二进制文件。我们也不希望 Electron 消费者从源代码构建 Electron,因为这既是一个巨大的技术挑战,而且时间和金钱成本也很高。

¥For a subset of Electron functionality it makes sense to disable certain features for an entire application. For example, 99% of apps don't make use of ELECTRON_RUN_AS_NODE, these applications want to be able to ship a binary that is incapable of using that feature. We also don't want Electron consumers building Electron from source as that is both a massive technical challenge and has a high cost of both time and money.

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

¥Fuses are the solution to this problem, at a high level they are "magic bits" in the Electron binary that can be flipped when packaging your Electron app to enable / disable certain features / restrictions. Because they are flipped at package time before you code sign your app the OS becomes responsible for ensuring those bits aren't flipped back via OS level code signing validation (Gatekeeper / App Locker).

当前保险丝

¥Current Fuses

runAsNode

默认:已启用

¥Default: Enabled

@electron/fuses:FuseV1Options.RunAsNode

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

¥The runAsNode fuse toggles whether the ELECTRON_RUN_AS_NODE environment variable is respected or not. Please note that if this fuse is disabled then process.fork in the main process will not function as expected as it depends on this environment variable to function. 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

默认:已禁用

¥Default: Disabled

@electron/fuses:FuseV1Options.EnableCookieEncryption

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

¥The cookieEncryption fuse toggles whether the cookie store on disk is encrypted using OS level cryptography keys. By default the sqlite database that Chromium uses to store cookies stores the values in plaintext. If you wish to ensure your apps cookies are encrypted in the same way Chrome does then you should enable this fuse. Please note it is a one-way transition, if you enable this fuse existing unencrypted cookies will be encrypted-on-write but if you then disable the fuse again your cookie store will effectively be corrupt and useless. Most apps can safely enable this fuse.

nodeOptions

默认:已启用

¥Default: Enabled

@electron/fuses:FuseV1Options.EnableNodeOptionsEnvironmentVariable

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

¥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. Most apps can safely disable this fuse.

nodeCliInspect

默认:已启用

¥Default: Enabled

@electron/fuses:FuseV1Options.EnableNodeCliInspectArguments

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

¥The nodeCliInspect fuse toggles whether the --inspect, --inspect-brk, etc. flags are respected or not. When disabled it also ensures that SIGUSR1 signal does not initialize the main process inspector. Most apps can safely disable this fuse.

embeddedAsarIntegrityValidation

默认:已禁用

¥Default: Disabled

@electron/fuses:FuseV1Options.EnableEmbeddedAsarIntegrityValidation

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

¥The embeddedAsarIntegrityValidation fuse toggles an experimental feature on macOS that validates the content of the app.asar file when it is loaded. This feature is designed to have a minimal performance impact but may marginally slow down file reads from inside the app.asar archive.

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

¥For more information on how to use asar integrity validation please read the Asar Integrity documentation.

onlyLoadAppFromAsar

默认:已禁用

¥Default: Disabled

@electron/fuses:FuseV1Options.OnlyLoadAppFromAsar

onlyLoadAppFromAsar 熔断器改变了 Electron 用于定位应用代码的搜索系统。默认情况下,Electron 会按照 app.asar -> app -> default_app.asar 的顺序进行搜索。当启用此熔丝时,搜索顺序变为单个条目 app.asar,从而确保与 embeddedAsarIntegrityValidation 熔丝结合时不可能加载未经验证的代码。

¥The onlyLoadAppFromAsar fuse changes the search system that Electron uses to locate your app code. By default Electron will search in the following order app.asar -> app -> default_app.asar. When this fuse is enabled the search order becomes a single entry app.asar thus ensuring that when combined with the embeddedAsarIntegrityValidation fuse it is impossible to load non-validated code.

loadBrowserProcessSpecificV8Snapshot

默认:已禁用

¥Default: Disabled

@electron/fuses:FuseV1Options.LoadBrowserProcessSpecificV8Snapshot

loadBrowserProcessSpecificV8Snapshot 熔断器更改浏览器进程使用的 V8 快照文件。默认情况下,Electron 的进程都将使用相同的 V8 快照文件。启用此保险丝后,浏览器进程将使用名为 browser_v8_context_snapshot.bin 的文件作为其 V8 快照。其他进程将像平常一样使用 V8 快照文件。

¥The loadBrowserProcessSpecificV8Snapshot fuse changes which V8 snapshot file is used for the browser process. By default Electron's processes will all use the same V8 snapshot file. When this fuse is enabled the browser process uses the file called browser_v8_context_snapshot.bin for its V8 snapshot. The other processes will use the V8 snapshot file that they normally do.

grantFileProtocolExtraPrivileges

默认:已启用

¥Default: Enabled

@electron/fuses:FuseV1Options.GrantFileProtocolExtraPrivileges

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

¥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.

下面不完整地记录了该熔丝授予 file:// 协议的额外权限:

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

  • file:// 协议页面可以使用 fetch 通过 file:// 加载其他资源

    ¥file:// protocol pages can use fetch to load other assets over file://

  • file:// 协议页面可以使用 Service Worker

    ¥file:// protocol pages can use service workers

  • 无论沙箱设置如何,file:// 协议页面都向同样在 file:// 协议上运行的子框架授予通用访问权限

    ¥file:// protocol pages have universal access granted to child frames also running on file:// protocols regardless of sandbox settings

如何翻转保险丝?

¥How do I flip the fuses?

最简单的方法

¥The easy way

我们制作了一个方便的模块 @electron/fuses,可以轻松翻转这些保险丝。查看该模块的自述文件,了解有关使用和潜在错误情况的更多详细信息。

¥We've made a handy module, @electron/fuses, to make flipping these fuses easy. Check out the README of that module for more details on usage and potential error cases.

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

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

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

¥You can validate the fuses have been flipped or check the fuse status of an arbitrary Electron app using the fuses CLI.

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

艰难的路

¥The hard way

快速词汇表

¥Quick Glossary

  • Fuse Wire:Electron 二进制文件中用于控制熔丝的字节序列

    ¥Fuse Wire: A sequence of bytes in the Electron binary used to control the fuses

  • 哨兵:可用于定位保险丝的静态已知字节序列

    ¥Sentinel: A static known sequence of bytes you can use to locate the fuse wire

  • Fuse Schema:保险丝的格式/允许值

    ¥Fuse Schema: The format / allowed values for the fuse wire

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

¥Manually flipping fuses requires editing the Electron binary and modifying the fuse wire to be the sequence of bytes that represent the state of the fuses you want.

在 Electron 二进制文件中的某个位置,会有一个如下所示的字节序列:

¥Somewhere in the Electron binary there will be a sequence of bytes that look like this:

| ...binary | sentinel_bytes | fuse_version | fuse_wire_length | fuse_wire | ...binary |
  • sentinel_bytes 始终是这个确切的字符串 dL7pKGdnNz796PbbjQWNKmHXBZaB9tsX

    ¥sentinel_bytes is always this exact string dL7pKGdnNz796PbbjQWNKmHXBZaB9tsX

  • fuse_version 是一个单字节,其无符号整数值表示熔丝模式的版本

    ¥fuse_version is a single byte whose unsigned integer value represents the version of the fuse schema

  • fuse_wire_length 是一个单字节,其无符号整数值代表后面的保险丝中的保险丝数量

    ¥fuse_wire_length is a single byte whose unsigned integer value represents the number of fuses in the following fuse wire

  • fuse_wire 是 N 个字节的序列,每个字节代表单个熔丝及其状态。

    ¥fuse_wire is a sequence of N bytes, each byte represents a single fuse and its state.

    • "0" (0x30) 表示保险丝已禁用

      ¥"0" (0x30) indicates the fuse is disabled

    • "1"(0x31)表示熔丝已使能

      ¥"1" (0x31) indicates the fuse is enabled

    • "r" (0x72) 表示熔丝已被移除,将字节更改为 1 或 0 将不起作用。

      ¥"r" (0x72) indicates the fuse has been removed and changing the byte to either 1 or 0 will have no effect.

要翻转保险丝,你需要找到其在保险丝中的位置,然后根据你想要的状态将其更改为 "0" 或 "1"。

¥To flip a fuse you find its position in the fuse wire and change it to "0" or "1" depending on the state you'd like.

你可以查看当前的架构 此处

¥You can view the current schema here.