Electron Fuses
打包时功能开关
什么是 Fuses?
从安全角度来看,禁用某些未使用的 Electron 功能是明智的。这些功能功能强大,但可能会削弱您应用程序的安全态势。例如,任何不使用 ELECTRON_RUN_AS_NODE 环境变量的应用程序都希望禁用该功能,以防止“驻留攻击”的子集。
我们也不希望 Electron 的消费者通过分支来达到此目的,因为从源码构建和维护分支是一项巨大的技术挑战,耗费大量时间和金钱。
Fuses 是解决此问题的方案。总的来说,它们是 Electron 二进制文件中的“魔法位”,可以在打包 Electron 应用程序时进行切换,以启用或禁用某些功能/限制。
由于它们在代码签名您的应用程序之前的打包时间进行切换,因此操作系统负责确保这些位不会通过操作系统级别的代码签名验证(例如 macOS 上的 Gatekeeper 或 Windows 上的 AppLocker)被改回。
当前 Fuses
runAsNode
默认: 已启用
@electron/fuses: FuseV1Options.RunAsNode
runAsNode Fuse 切换是否遵循 ELECTRON_RUN_AS_NODE 环境变量。禁用此 Fuse 后,主进程中的 child_process.fork 将无法按预期工作,因为它依赖于此环境变量才能运行。相反,我们建议您使用 Utility Processes,它适用于许多需要独立 Node.js 进程(例如 SQLite 服务器进程)的用例。
cookieEncryption
默认: 已禁用
@electron/fuses: FuseV1Options.EnableCookieEncryption
cookieEncryption Fuse 切换是否使用操作系统级别的加密密钥加密磁盘上的 Cookie 存储。默认情况下,Chromium 用于存储 Cookie 的 SQLite 数据库以明文形式存储值。如果您希望确保您的应用程序的 Cookie 与 Chrome 的加密方式相同,则应启用此 Fuse。请注意,这是一个单向转换——如果您启用此 Fuse,现有未加密的 Cookie 将在写入时被加密,但之后禁用该 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 和 Windows 上启用一项功能,该功能会验证加载 app.asar 文件时的内容。此功能旨在对性能影响最小,但可能会略微减慢从 app.asar 存档内部进行的文件读取速度。大多数应用程序都可以安全地启用此 Fuse。
有关 ASAR 完整性验证如何使用的更多信息,请阅读 Asar Integrity 文档。
onlyLoadAppFromAsar
默认: 已禁用
@electron/fuses: FuseV1Options.OnlyLoadAppFromAsar
onlyLoadAppFromAsar Fuse 会更改 Electron 用于查找应用程序代码的搜索系统。默认情况下,Electron 将按以下顺序搜索此代码:
app.asarappdefault_app.asar
启用此 Fuse 后,Electron 将仅搜索 app.asar。当与 embeddedAsarIntegrityValidation Fuse 结合使用时,此 Fuse 可确保不可能加载未经验证的代码。
loadBrowserProcessSpecificV8Snapshot
默认: 已禁用
@electron/fuses: FuseV1Options.LoadBrowserProcessSpecificV8Snapshot
V8 快照有助于提高应用程序的启动性能。V8 允许您创建已初始化的堆的快照,然后将其重新加载,从而避免初始化堆的开销。
loadBrowserProcessSpecificV8Snapshot Fuse 会更改用于浏览器进程的 V8 快照文件。默认情况下,Electron 的所有进程都将使用相同的 V8 快照文件。启用此 Fuse 后,主进程将使用名为 browser_v8_context_snapshot.bin 的文件作为其 V8 快照。其他进程将使用它们通常使用的 V8 快照文件。
为渲染器进程和主进程使用单独的快照可以提高安全性,尤其可以确保渲染器不使用启用了 nodeIntegration 的快照。有关详细信息,请参阅 electron/electron#35170。
grantFileProtocolExtraPrivileges
默认: 已启用
@electron/fuses: FuseV1Options.GrantFileProtocolExtraPrivileges
grantFileProtocolExtraPrivileges Fuse 会更改从 file:// 协议加载的页面所获得的权限,使其超出传统浏览器所能获得的权限。此行为是早期版本 Electron 中 Electron 应用程序的核心功能,但现在不再需要,因为应用程序应 使用自定义协议提供本地文件 而非 file://。
如果您不使用 file:// 提供页面,则应禁用此 Fuse。
此 Fuse 授予 file:// 协议的额外权限如下文所述(不完全):
file://协议页面可以使用fetch通过file://加载其他资源file://协议页面可以使用 Service Workerfile://协议页面对同样运行在file://协议上的子框架拥有通用访问权限,无论沙盒设置如何
如何切换 Fuses?
简单方法
@electron/fuses 是一个 JavaScript 工具,旨在轻松切换这些 Fuses。有关使用方法和潜在错误情况的更多详细信息,请查看该模块的 README。
const { flipFuses, FuseVersion, FuseV1Options } = require('@electron/fuses')
flipFuses(
// Path to electron
require('electron'),
// Fuses to flip
{
version: FuseVersion.V1,
[FuseV1Options.RunAsNode]: false
}
)
您可以使用 @electron/fuses CLI 来验证已切换的 Fuses 或检查任意 Electron 应用程序的 Fuse 状态。
npx @electron/fuses read --app /Applications/Foo.app
如果您使用 Electron Forge 分发您的应用程序,则可以使用 @electron-forge/plugin-fuses 来切换 Fuses,该插件已预装在所有模板中。
困难方法
术语表
- Fuse Wire:Electron 二进制文件中用于控制 Fuses 的字节序列
- Sentinel:用于定位 Fuse Wire 的静态已知字节序列
- Fuse Schema:Fuse Wire 的格式/允许值
手动切换 Fuses 需要编辑 Electron 二进制文件并修改 Fuse Wire,使其成为表示您想要的 Fuse 状态的字节序列。
在 Electron 二进制文件的某个位置,将存在一个如下所示的字节序列:
| ...binary | sentinel_bytes | fuse_version | fuse_wire_length | fuse_wire | ...binary |
sentinel_bytes始终是此确切字符串:dL7pKGdnNz796PbbjQWNKmHXBZaB9tsXfuse_version是一个单字节,其无符号整数值表示 Fuse Schema 的版本fuse_wire_length是一个单字节,其无符号整数值表示后续 Fuse Wire 中 Fuse 的数量fuse_wire是 N 个字节的序列,每个字节代表一个 Fuse 及其状态。- “0” (0x30) 表示 Fuse 已禁用
- “1” (0x31) 表示 Fuse 已启用
- “r” (0x72) 表示 Fuse 已被移除,将该字节更改为 1 或 0 都不会产生任何效果。
要切换 Fuse,您需要找到它在 Fuse Wire 中的位置,并根据您想要的状态将其更改为“0”或“1”。
您可以在 此处 查看当前 Schema。