跳转至

进程沙箱

Chromium 的一项关键安全特性是,进程可以在沙箱中执行。 沙箱通过限制对大多数系统资源的访问来限制恶意代码可能造成的损害——沙箱化进程只能自由使用 CPU 周期和内存。 为了执行需要额外权限的操作,沙箱化进程使用专用通信通道将任务委托给权限更高的进程。

在 Chromium 中,除主进程外,沙箱应用于大多数进程。 这包括渲染进程,以及诸如音频服务、GPU 服务和网络服务等工具进程。

有关更多信息,请参阅 Chromium 的 沙箱设计文档。

从 Electron 20 开始,渲染进程的沙箱无需任何额外配置即可启用。

沙箱与 Node.js 集成相关联。通过设置 nodeIntegration: true 为渲染进程 启用 Node.js 集成 会 禁用该进程的沙箱。

如果你想为某个进程禁用沙箱,请参阅 为单个进程禁用沙箱 部分。

Electron 中的沙箱行为

Electron 中的沙箱化进程的行为 基本上 与 Chromium 中的相同,但由于 Electron 与 Node.js 交互,因此有几个额外的概念需要考虑。

渲染进程

当 Electron 中的渲染进程被沙箱化时,其行为与常规 Chromium 渲染进程相同。沙箱化渲染进程不会初始化 Node.js 环境。

因此,当启用沙箱时,渲染进程只能通过进程间通信(IPC)将这些任务委托给主进程,才能执行特权任务(例如与文件系统交互、对系统进行更改或生成子进程)。

:::note

有关进程间通信的更多信息,请查看我们的 IPC 指南。

:::

预加载脚本

为了允许渲染进程与主进程通信,附加到沙箱化渲染进程的预加载脚本会在作用域中带有几个额外的值运行:

  • require - 一个只能加载 electron 模块(也可作为 electron/renderer 和 electron/common 使用)的函数,其中包含渲染进程 模块:contextBridge、crashReporter、ipcRenderer、nativeImage、webFrame 和 webUtils。
  • process - 一个精简的 process 对象。
  • global - 预加载脚本的 globalThis 的别名。

Node.js 内置模块或 Node.js 全局变量(如 Buffer 或 setImmediate) 不可用。请改用等效的 Web API(Uint8Array、TextEncoder/TextDecoder、 URL、EventTarget、setTimeout/queueMicrotask),或者将 polyfill 打包到你的预加载脚本中。

由于这个 require 函数无法加载文件,因此你无法使用 CommonJS 模块 将预加载脚本拆分为多个文件。如果 你需要拆分预加载代码,请使用 webpack 或 Parcel 等打包器。

请注意,由于提供给 preload 脚本的环境比沙箱化渲染进程的环境拥有多得多的权限,因此除非启用 contextIsolation,否则仍然可能将特权 API 泄露给在渲染进程中运行的不受信任代码。

配置沙箱

对于大多数应用而言,沙箱是最佳选择。在某些与沙箱不兼容的使用场景中 (例如,在渲染进程中使用原生 Node.js 模块时), 可以为特定进程禁用沙箱。这会带来安全风险,尤其是在未沙箱化进程中存在任何不受信任的代码或内容时。

为单个进程禁用沙箱

在 Electron 中,可以通过 BrowserWindow 构造函数中的 sandbox: false 偏好设置,按进程禁用渲染进程沙箱。

main.js
app.whenReady().then(() => {
  const win = new BrowserWindow({
    webPreferences: {
      sandbox: false
    }
  })
  win.loadURL('https://google.com')
})

只要启用渲染进程中的 Node.js 集成,沙箱也会被禁用。 可以通过 BrowserWindow 构造函数中的 nodeIntegration: true 标志完成, 或者为 webview 提供相应的 HTML 布尔属性。

main.js
app.whenReady().then(() => {
  const win = new BrowserWindow({
    webPreferences: {
      nodeIntegration: true
    }
  })
  win.loadURL('https://google.com')
})
index.html (Renderer Process)
<webview nodeIntegration src="page.html"></webview>

全局启用沙箱

如果你想强制为所有渲染器启用沙箱,也可以使用 app.enableSandbox API。请注意,此 API 必须在 应用的 ready 事件之前调用。

main.js
app.enableSandbox()
app.whenReady().then(() => {
  // any sandbox:false calls are overridden since `app.enableSandbox()` was called.
  const win = new BrowserWindow()
  win.loadURL('https://google.com')
})

禁用 Chromium 的沙箱(仅用于测试)

你也可以使用 --no-sandbox CLI 标志完全禁用 Chromium 的沙箱,这将禁用所有进程(包括工具进程)的沙箱。 我们强烈建议你仅将此标志用于测试目的,并且永远不要 在生产环境中使用。

请注意,sandbox: true 选项仍会禁用渲染进程的 Node.js 环境。

关于渲染不受信任内容

在 Electron 中渲染不受信任的内容仍然是一个尚未完全探索的领域, 尽管一些应用已经取得了成功(例如 Beaker Browser)。 我们的目标是在沙箱化内容的安全性方面尽可能接近 Chrome,但由于一些根本 问题,我们最终总会落后:

  1. 我们没有 Chromium 用于其产品安全的专门资源或专业知识。我们尽最大努力利用我们 所拥有的资源,尽可能从 Chromium 继承一切,并快速响应 安全问题,但如果没有 Chromium 能够投入的资源,Electron 无法像 Chromium 一样安全。
  2. Chrome 中的一些安全功能(例如 Safe Browsing 和 Certificate Transparency)需要集中式权威和专用服务器,这两者都与 Electron 项目的目标相悖。因此,我们在 Electron 中禁用了 这些功能,代价是失去了它们本应带来的相关安全性。
  3. 只有一个 Chromium,而基于 Electron 构建的应用有成千上万个,它们的行为都略有不同。考虑这些 差异可能会产生巨大的可能性空间,并使确保平台在异常使用场景中的安全性变得具有挑战性。
  4. 我们无法直接向用户推送安全更新,因此我们依赖应用供应商 升级其应用底层 Electron 的版本,以便安全更新能够到达用户。

尽管我们尽最大努力将 Chromium 安全修复回移到旧版本的 Electron,但我们不保证每个修复都会被回移。保持安全的最佳方式是使用最新稳定版本的 Electron。

本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 el/electron