Electron contextIsolation
contextIsolation 把 preload/Electron 内部逻辑与页面脚本放在不同 JavaScript context 中,防止页面直接篡改高权限桥接环境;它自 Electron 12 起默认开启,但仍必须与 sandbox、最小权限 contextBridge 和 IPC sender validation 组合使用。
[!info] related notes
- 所属 MOC: Electron MOC
- Preload: Electron preload 脚本
- Bridge: Electron contextBridge
- Sandbox: Electron 进程沙箱
- 安全: Electron 安全检查清单
Electron contextIsolation
一句话定义
contextIsolation 让:
preload / Electron internal context
与
renderer page / Main World
运行在不同 JavaScript context。
它的目标是:
页面脚本即使修改自己的全局对象和 prototype,也不能直接修改 preload / Electron 所在隔离世界中的对象。
为什么需要隔离
如果 preload 和页面共享同一个 context:
- 页面可以改写全局对象;
- XSS 更容易接触高权限桥接变量;
- preload 的内部状态更容易被页面污染。
开启 contextIsolation 后:
- 页面只看到 contextBridge 明确暴露的接口;
- preload 自己的全局对象仍在 Isolated World;
- Electron internals 与网页环境隔离。
默认状态
contextIsolation 自 Electron 12 起默认开启。
因此现代 Electron 项目不应把:
contextIsolation: false
当成普通兼容配置。
关闭它是在放宽安全边界。
与 Sandbox 的关系
contextIsolation 和 sandbox 不是同一个机制。
contextIsolation:
隔离 JavaScript context。
Sandbox:
限制 renderer process 能使用的系统/Node 能力。
所以:
contextIsolation = true
不能推出:
renderer fully sandboxed
反过来也不能只开 sandbox 就忽略 API 暴露边界。
现代安全模型通常组合:
- nodeIntegration: false;
- contextIsolation: true;
- sandbox: true;
- narrow preload API;
- restrictive CSP;
- IPC sender validation。
与 nodeIntegration
nodeIntegration 控制页面是否直接获得 Node.js integration。
contextIsolation 控制页面和 preload/Electron internal logic 是否共享 context。
二者是不同维度。
安全设计里:
关闭 nodeIntegration 仍然不意味着可以关闭 contextIsolation。
Electron 官方安全指南也明确要求启用 context isolation。
Prototype Pollution / Global Mutation
contextIsolation 的一个实际价值是:
页面修改:
Array.prototype
JSON.parse
window.someGlobal
不会直接修改 preload 的隔离世界中对应对象。
这降低了页面内容污染 privileged bridge implementation 的风险。
但如果你主动把一个危险 capability 暴露进页面,隔离本身不会帮你重新收回权限。
contextIsolation 不是 Capability Policy
例如你暴露:
window.appApi.runCommand(command)
即使 contextIsolation 开启,这仍可能是极高风险 API。
所以:
contextIsolation
≠ safe API design
它只能提供隔离基础。
真正 capability policy 仍由:
- preload API surface;
- main validation;
- sender validation;
- permission policy;
决定。
与 contextBridge
推荐结构:
Isolated World preload
→ contextBridge
→ narrow renderer API
contextBridge 是穿过 isolation boundary 的显式桥梁。
不要为了“共享 window 对象方便”而关闭 contextIsolation。
远程内容风险
如果 BrowserWindow 加载远程内容,renderer compromise 的可能性和影响都更需要严格控制。
此时尤其应该:
- 不启用 Node integration;
- 保持 contextIsolation;
- 保持 sandbox;
- 不暴露 Electron API;
- 限制 navigation/new window;
- 使用 CSP。
常见误区
contextIsolation = sandbox
错误,它们隔离的层级不同。
开启 contextIsolation 就安全了
错误,危险 API 仍然危险。
preload 和 renderer 不能通信
错误,应通过 contextBridge / IPC 暴露明确 contract。
本地 HTML 就可以随便关
本地内容同样可能受到 dependency/XSS/injection 问题影响,安全边界仍然有价值。
学习检查
- contextIsolation 隔离的到底是什么?
- 为什么它与 sandbox 不是同一个机制?
- nodeIntegration=false 为什么不能替代 contextIsolation?
- contextIsolation 怎样降低 prototype/global pollution 对 preload 的影响?
- 为什么一个危险的 runCommand() API 在 isolation 开启后仍然危险?
- contextBridge 在 isolation 模型中扮演什么角色?
- 给一个加载远程 dashboard 的 BrowserWindow,列出至少五项安全基线。