Electron BrowserWindow
BrowserWindow 是主进程创建窗口和配置 renderer 运行边界的核心对象;webPreferences 决定 preload、nodeIntegration、contextIsolation、sandbox、session 等能力,窗口创建因此同时是 UI 与安全边界设计。
[!info] related notes
- 所属 MOC: Electron MOC
- 进程: Electron 主进程, Electron 渲染进程
- Preload: Electron preload 脚本
- Isolation: Electron contextIsolation
- Sandbox: Electron 进程沙箱
- WebContents: Electron WebContents
- 安全: Electron 安全检查清单
Electron BrowserWindow
一句话定义
BrowserWindow 不只是“桌面窗口控件”。
它同时定义:
- native window;
- renderer WebContents;
- preload;
- session;
- renderer privilege/security boundary。
因此创建窗口时的 webPreferences 是架构配置,不只是 UI 配置。
Main Process Ownership
BrowserWindow 由 main process 创建和管理。
典型职责:
- create/destroy window;
- load local/remote content;
- window state;
- native controls;
- renderer lifecycle;
- webContents integration。
renderer 不应该自己拥有创建任意 BrowserWindow 的高权限能力。
webPreferences 是关键边界
最常见:
- preload;
- nodeIntegration;
- contextIsolation;
- sandbox;
- session / partition;
- webviewTag;
- devTools;
- additionalArguments 等。
这些选项共同决定:
页面被攻陷后能接触到什么能力。
当前安全默认
当前 Electron:
- nodeIntegration 默认 false;
- contextIsolation 默认 true;
- sandbox 默认 true(Electron 20 起)。
所以新项目首先应该:
保持安全默认,而不是为了旧代码方便把它们关闭。
nodeIntegration
nodeIntegration=true 会让 renderer 页面直接获得 Node integration。
如果页面存在 XSS,风险可能从:
Web content compromise
升级为:
local system capability compromise
所以远程内容尤其不能启用 Node integration。
contextIsolation
contextIsolation 让 preload / Electron internal logic 与页面运行在不同 JavaScript context。
它降低页面直接污染 privileged bridge 的风险。
sandbox
sandbox=true 使 renderer 使用 Chromium OS-level sandbox,并限制 preload 能使用的 Node/Electron API 范围。
重要关系:
nodeIntegration=true 会自动关闭该 renderer 的 sandbox。
因此不能把:
nodeIntegration=true + sandbox=true
理解成两个独立开关可以同时保持完整效果。
Preload
preload 在页面脚本之前运行。
它负责把少量 capability 通过 contextBridge 暴露给 renderer。
BrowserWindow 配置 preload path,但:
BrowserWindow 不应该因此把完整 Electron/Node surface 暴露给页面。
Session / Partition
BrowserWindow 可以使用:
- default session;
- explicit Session;
- partition。
这影响:
- cookies;
- cache;
- proxy;
- permissions;
- storage;
- network behavior。
因此多账号、隔离 workspace、隐私窗口等场景要明确 session ownership。
loadFile vs loadURL
loadFile 常用于 packaged local UI。
loadURL 可以加载:
- localhost dev server;
- trusted HTTPS;
- remote content。
如果加载 remote content,安全假设必须更严格:
- no Node integration;
- context isolation;
- sandbox;
- restrictive CSP;
- permission handling;
- navigation/window restrictions;
- narrow IPC。
Navigation Boundary
BrowserWindow 初始加载可信页面,不意味着之后永远停留在该页面。
需要考虑:
- will-navigate;
- window.open;
- external links;
- redirects;
- embedded frames。
如果导航到攻击者页面,但 preload API 仍然可用,就可能形成 capability leak。
window.open
新窗口创建必须显式控制。
不要让任意网页直接创建拥有应用 preload/privilege 的新 BrowserWindow。
可通过 WebContents 的 window-open handler:
- deny;
- allow selected URL;
- open external browser;
来限定行为。
DevTools
devTools 默认开启本身不等于 production 安全漏洞。
真正风险取决于:
- 用户能否接触 privileged renderer;
- debug interface 是否暴露;
- production threat model。
不要通过“禁 DevTools”替代正确的 privilege separation。
BrowserWindow 与 WebContents
BrowserWindow 是 native window container。
WebContents 是其中网页内容的运行/导航/IPC载体。
很多页面行为:
- navigation;
- download;
- permission;
- open window;
- send IPC;
实际由 WebContents 层处理。
一个安全基线
一个普通本地 renderer 可以先从:
nodeIntegration: false
contextIsolation: true
sandbox: true
preload: narrow bridge
开始。
再根据真实需求逐项增加 capability,而不是先开权限再补安全。
常见误区
BrowserWindow 只是 UI 配置
错误。webPreferences 本质上定义运行权限边界。
local HTML 没有 XSS 风险
错误。dependency、用户数据、Markdown/HTML render 都可能产生 injection。
preload 有了就可以关闭 contextIsolation
错误。preload 正需要隔离才能成为安全 bridge。
sandbox=false 只是兼容选项,没有安全成本
错误。它扩大 renderer compromise 后的可用能力。
学习检查
- BrowserWindow 为什么既是 UI 对象也是 security boundary?
- nodeIntegration、contextIsolation、sandbox 分别控制哪一层?
- 为什么 nodeIntegration=true 会影响 sandbox?
- session/partition 为什么属于窗口架构,而不只是缓存配置?
- remote content BrowserWindow 需要额外收紧哪些边界?
- 为什么初始 URL 可信还不够,还要限制 navigation/window.open?
- 给一个加载本地 React UI 的 BrowserWindow 写出最小安全配置心智模型。