Electron 进程沙箱
Electron sandbox 基于 Chromium 的 OS-level renderer sandbox,限制 renderer 直接访问 Node/系统能力;自 Electron 20 起默认启用,但 nodeIntegration=true 会自动关闭该 renderer 的 sandbox,且 sandbox 仍需与 contextIsolation 和窄 preload API 组合。
[!info] related notes
- 所属 MOC: Electron MOC
- 进程模型: Electron 进程模型
- Context: Electron contextIsolation
- Window: Electron BrowserWindow
- Preload: Electron preload 脚本
- 安全: Electron 安全检查清单
Electron 进程沙箱
一句话定义
Electron sandbox 使用 Chromium 的进程隔离模型和操作系统安全机制限制 renderer process。
目标是:
即使 renderer 中的网页代码被攻陷,也尽量让攻击者停留在低权限进程内。
它限制什么
sandboxed renderer 默认不能直接获得完整 Node.js runtime。
这意味着页面无法直接:
- require 任意 Node module;
- 读写 filesystem;
- 启动 child process;
- 调用大量 OS capability。
高权限操作应该通过:
renderer
→ preload
→ IPC
→ main
完成。
Electron 20 默认行为
自 Electron 20 起,renderer sandbox 默认开启。
因此:
sandbox: false
应该被视为显式放宽安全边界,而不是无意义兼容项。
nodeIntegration 的影响
一个重要默认关系:
nodeIntegration=true 会自动关闭该 renderer 的 sandbox。
因为完整 Node integration 与 Chromium sandbox 的隔离模型冲突。
所以不要认为:
nodeIntegration=true
sandbox=true
仍然保留完整 sandbox 保护。
Sandbox 与 contextIsolation
两者层级不同:
sandbox
限制进程能够访问什么系统能力。
contextIsolation
隔离:
- preload / Electron internals;
- page JavaScript context。
因此安全基线通常是同时:
sandbox=true
contextIsolation=true
二者不能互相替代。
Sandboxed Preload
即使 renderer sandbox 开启,preload 仍然比普通页面更有能力。
但它不拥有完整 Node environment。
sandboxed preload 只能访问受限 API subset。
这也是为什么:
复杂 OS / filesystem 逻辑应该放到 main process,而不是塞进 preload。
为什么 Preload 仍然危险
sandbox 不会阻止开发者主动泄漏 capability。
例如 preload 暴露:
window.appApi.readAnyFile(path)
攻击者即使被 sandbox,也可以通过该 API 请求高权限 main operation。
所以真正模型是:
OS sandbox
- context isolation
- narrow preload API
- IPC validation
共同构成防线。
Remote Content
如果 renderer 加载 remote/untrusted content,sandbox 的价值尤其高。
Electron 官方明确建议:
- remote content 不启用 Node integration;
- 开启 context isolation;
- 开启 process sandboxing。
否则普通 XSS 可能升级为本地系统 compromise。
Utility / Main Process 边界
sandbox 主要解决 renderer process 风险。
Main process 本身通常拥有高权限。
因此:
把不可信 HTML/JS 逻辑挪到 main 并不会变安全,反而可能更危险。
不可信内容应该尽量留在低权限隔离进程。
什么时候可能关闭 sandbox
某些 legacy/native module 场景可能与 sandbox 不兼容。
但关闭前应该明确回答:
- 为什么必须关闭?
- 哪个 window/process?
- 页面是否完全本地且可信?
- preload 暴露面多大?
- 能否把不兼容能力迁到 main/utility process?
- 是否有额外 compensating controls?
不要全局关闭只为解决一个 dependency。
常见误区
sandbox = contextIsolation
错误,一个是 process capability,一个是 JS context。
sandbox 打开就不怕 XSS
错误。XSS 仍能操作页面和暴露的 preload API。
preload 不受 sandbox 影响
错误。sandboxed preload 的 Node/Electron 能力受限制。
main process 也应该直接渲染不可信网页
错误。main 是高权限控制层,不应该承担不可信 Web content。
学习检查
- Electron sandbox 的直接保护对象是什么?
- sandbox 与 contextIsolation 分别隔离哪一层?
- 为什么 nodeIntegration=true 会削弱/关闭 renderer sandbox?
- sandboxed preload 为什么不应承担大量 filesystem 逻辑?
- sandbox 开启后,危险 preload API 为什么仍然危险?
- 什么时候可以考虑 sandbox=false,必须补哪些风险论证?
- 一个加载远程内容的窗口为什么应同时使用 sandbox + contextIsolation + narrow preload?