跳转到主内容

安全

报告安全问题

有关如何正确上报 Electron 漏洞的信息,请参阅 SECURITY.md。

对于上游 Chromium 漏洞: Electron 用其他版本的 Chromium 来更新。 要了解更多信息,请参阅 Electron 发布时间线 文档。

前言​

作为网络开发人员,我们通常喜欢浏览器的强大安全网,因为这样我们编写的代码风险较小。 我们的网站在沙盒中被赋予了有限的权力,我们相信我们的用户享受到的是一个由大型工程师团队打造的浏览器,它能够快速应对新发现的安全威胁。

当使用 Electron 时,很重要的一点是要理解 Electron 不是一个 Web 浏览器。 它允许您使用熟悉的 Web 技术构建功能丰富的桌面应用程序,但是您的代码具有更强大的功能。 JavaScript 可以访问文件系统,用户 shell 等。 这允许您构建更高质量的本机应用程序,但是内在的安全风险会随着授予您的代码的额外权力而增加。

考虑到这一点,请注意,展示任意来自不受信任源的内容都将会带来严重的安全风险,而这种风险Electron也没打算处理。 事实上,最流行的 Electron 应用程序(Atom,Slack,Visual Studio Code 等) 主要显示本地内容(即使有远程内容也是无 Node 的、受信任的、安全的内容) - 如果您的应用程序要运行在线的源代码,那么您需要确保源代码不是恶意的。

一般准则​

安全是所有人的共同责任​

需要牢记的是,你的 Electron 程序安全性除了依赖于整个框架基础(Chromium、Node.js)、Electron 本身和所有相关 NPM 库的安全性,还依赖于你自己的代码安全性。 因此,你有责任遵循下列安全守则:

  • **使用最新版的 Electron 框架搭建你的程序。**你最终发行的产品中会包含 Electron、Chromium 共享库和 Node.js 的组件。 这些组件存在的安全问题也可能影响你的程序安全性。 你可以通过更新Electron到最新版本来确保像是_nodeIntegration绕过攻击_一类的严重漏洞已经被修复因而不会影响到你的程序。 请参阅“使用当前版本的Electron”以获取更多信息。

  • 评估你的依赖项目NPM提供了五百万可重用的软件包,而你应当承担起选择可信任的第三方库。 如果你使用了受已知漏洞的过时的库,或是依赖于维护的很糟糕的代码,你的程序安全就可能面临威胁。

  • 遵循安全编码实践你的代码是你的程序安全的第一道防线。 一般的网络漏洞,例如跨站脚本攻击(Cross-Site Scripting, XSS),对Electron将造成更大的影响,因此非常建议你遵循安全软件开发最佳实践并进行安全性测试。

隔离不受信任的内容​

每当你从不被信任的来源(如一个远程服务器)获取代码并在本地执行,其中就存在安全性问题。 例如在一个默认的 BrowserWindow 中显示一个远程网站。 如果攻击者以某种方式设法改变所述内容 (通过直接攻击源或者通过在应用和实际目的地之间进行攻击) ,他们将能够在用户的机器上执行本地代码。

:::警告

无论如何,在启用Node.js集成的情况下,你都不该加载并执行远程代码。 相反,只使用本地文件(和您的应用打包在一起)来执行Node.js代码 要显示远程内容,请使用 <webview> 或 WebContentsView,并确保禁用 nodeIntegration,以及启用 contextIsolation 。

:::

Electron 安全警告

安全警告和建议被打印到开发者控制台。 只有当二进制文件的名称为Electron时,它们才会显示,这表明开发人员 当前正在查看控制台。

你可以通过在process.env 或 window对象上配置ELECTRON_ENABLE_SECURITY_WARNINGS 或ELECTRON_DISABLE_SECURITY_WARNINGS来强制开启或关闭这些警告。

清单:安全建议​

为加强程序安全性,你至少应当遵循下列规则:

  1. 只加载安全的内容
  2. 不要为远程内容启用 Node.js 集成
  3. 在所有渲染器中启用上下文隔离
  4. 启用进程沙盒化
  5. 在所有加载远程内容的会话中使用 ses.setPermissionRequestHandler().
  6. 不要禁用 webSecurity
  7. 定义一个Content-Security-Policy并设置限制规则(如:script-src 'self')
  8. 不要设置 allowRunningInsecureContent 为 true
  9. 不要开启实验性功能
  10. 不要使用enableBlinkFeatures
  11. <webview>:不要使用 allowpopups
  12. <webview>:验证选项与参数
  13. 禁用或限制网页跳转
  14. 禁用或限制新窗口创建
  15. 不要对不可信的内容使用 shell.openExternal
  16. 使用当前版本的 Electron
  17. 验证所有 IPC 消息的 sender
  18. 不要使用 file://,而是使用自定义协议
  19. 检查你可以修改哪些 Fuse
  20. 请勿将 Electron API 暴露给不受信任的网络内容

1. 只加载安全的内容​

任何不属于你的应用的资源都应该使用像HTTPS这样的安全协议来加载。 换言之, 不要使用不安全的协议 (如 HTTP)。 同理,我们建议使用WSS,避免使用WS,建议使用FTPS ,避免使用FTP,等等诸如此类的协议。

为什么?​

HTTPS 有两个主要好处:

  1. 确保数据完整性,断言数据在您的应用程序和主机之间传输时未被修改。
  2. 它会加密您的用户和目标主机之间的流量,使窃听应用与主机之间发送的信息变得更加困难。

怎么做?​

main.js (Main Process)
// 不推荐
browserWindow.loadURL ('http://example.com')
// 推荐
browserWindow.loadURL ('https://example.com')
index.html (Renderer Process)
<!-- 不推荐 -->
<script crossorigin src="http://example.com/react.js"></script>
<link rel="stylesheet" href="http://example.com/style.css">

<!-- 推荐 -->
<script crossorigin src="https://example.com/react.js"></script>
<link rel="stylesheet" href="https://example.com/style.css">

2. 不要为远程内容启用 Node.js 集成​

info

此建议是 Electron 自 5.0.0 以来的默认行为。

在任何加载远程内容的渲染器( BrowserWindow、WebContentsView 或 <webview> )中禁止 Node.js 集成极为重要。 其目的是限制您授予远程内容的权限, 从而使攻击者在您的网站上执行 JavaScript 时更难伤害您的用户。

在此之后,你可以为指定的主机授予附加权限。 举例来说,如果你正在打开一个指向 https://example.com/ 的 BrowserWindow,那么你可以给他刚刚好足够的权限,但是绝对不要超出这个范围。

为什么?​

如果攻击者跳过渲染进程并在用户电脑上执行恶意代码,那么这种跨站脚本(XSS) 攻击的危害是非常大的。 跨站脚本攻击很常见,通常情况下,威力仅限于执行代码的网站。 禁用Node.js集成有助于防止XSS攻击升级为“远程代码执行” (RCE) 攻击。

怎么做?​

main.js (Main Process)
// 不推荐
const mainWindow = new BrowserWindow({
webPreferences: {
contextIsolation: false,
nodeIntegration: true,
nodeIntegrationInWorker: true
}
})

mainWindow.loadURL('https://example.com')
main.js (Main Process)
// 推荐
const mainWindow = new BrowserWindow({
webPreferences: {
preload: path.join(app.getAppPath(), 'preload.js')
}
})

mainWindow.loadURL('https://example.com')
index.html (Renderer Process)
<!-- 不推荐 -->
<webview nodeIntegration src="page.html"></webview>

<!-- 推荐 -->
<webview src="page.html"></webview>

当禁用Node.js集成时,你依然可以暴露API给你的站点以使用Node.js的模块功能或特性。 预加载脚本依然可以使用 require 等 Node.js 特性, 允许开发者通过 contextBridge API 向远程加载的内容暴露自定义 API。

3. 上下文隔离​

info

上下文隔离是 Electron 自 12.0.0 以来的默认行为。

上下文隔离是Electron的一个特性,它允许开发者在预加载脚本里运行代码,里面包含Electron API和专用的JavaScript上下文。 实际上,这意味全局对象如 Array.prototype.push 或 JSON.parse等无法被渲染进程里的运行脚本修改。

Electron使用了和Chromium相同的Content Scripts技术来开启这个行为。

即便使用了 nodeIntegration: false, 要实现真正的强隔离并且防止使用 Node.js 的功能, contextIsolation 也 必须 开启.

注意,设置 nodeIntegration: true 不仅会禁用一个渲染进程的_上下文隔离_,还会禁用该进程的_进程沙盒化_。 请参阅下面的小节。

info

关于什么是 contextIsolation 以及如何启用它的信息,请参阅我们专门的上下文隔离文档。

4. 启用进程沙盒化​

info

此建议是 Electron 自 20.0.0 以来的默认行为。

此外,还可以强制启用应用程序内所有渲染进程的进程沙盒化:全局启用沙盒。

不管是否使用了默认值,sandbox: false 还是全局启用沙盒化,禁用上下文隔离(见上)也会禁用进程沙盒化!

沙盒 是一项 Chromium 功能,它使用操作系统来显著地限制渲染器进程可以访问的内容。 您应该在所有渲染器中启用沙盒。 不建议在一个未启动沙盒的进程(包括主进程)中加载、阅读或处理任何不信任的内容。

info

关于什么是进程沙盒化以及如何启用它的信息,请参阅我们专门的进程沙盒化文档。

5. 处理来自远程内容的会话许可的请求​

当你使用Chrome时,也许见过这种许可请求:每当网站尝试使用某个特性时,就会弹出让用户手动确认(如网站通知)

此API基于Chromium permissions API,并已实现对应的许可类型。

为什么?​

默认情况下,Electron将自动批准所有的许可请求,除非开发者手动配置一个自定义处理函数。 尽管默认如此,有安全意识的开发者可能希望默认反着来。

怎么做?​

main.js (Main Process)
const { session } = require('electron')

const { URL } = require('node:url')

session
.defaultSession
.setPermissionRequestHandler((webContents, permission, callback) => {
const parsedUrl = new URL(webContents.getURL())

if (permission === 'notifications') {
// Approves the permissions request
callback(true)
}

// Verify URL
if (parsedUrl.protocol !== 'https:' || parsedUrl.host !== 'example.com') {
// Denies the permissions request
return callback(false)
}
})

注意:仅当调用了 app.whenReady 后才能使用 session.defaultSession 。

6. 不要禁用 webSecurity​

info

此建议是 Electron 的默认值。

你应该已经猜到了,在渲染进程( BrowserWindow、WebContentsView 或 <webview> )中禁用 webSecurity 属性将会使重要的安全特性失效。

不要在生产环境中禁用webSecurity。

为什么?​

禁用 webSecurity 将会禁止同源策略并且将 allowRunningInsecureContent 属性置 true。 换句话说,这将使得来自其他站点的非安全代码被执行。

怎么做?​

main.js (Main Process)
// 不推荐
const mainWindow = new BrowserWindow({
webPreferences: {
webSecurity: false
}
})
main.js (Main Process)
// 推荐
const mainWindow = new BrowserWindow()
index.html (Renderer Process)
<!-- 不推荐 -->
<webview disablewebsecurity src="page.html"></webview>

<!-- 推荐 -->
<webview src="page.html"></webview>

7. Content Security Policy(内容安全策略)​

内容安全策略(CSP) 是应对跨站脚本攻击和数据注入攻击的又一层保护措施。 我们建议任何载入到Electron的站点都要开启。

为什么?​

CSP允许Electron通过服务端内容对指定页面的资源加载进行约束与控制。 如果你定义https://example.com这个源,所属这个源的脚本都允许被加载,反之https://evil.attacker.com不会被允许加载运行。 对于提升你的应用安全性,设置CSP是个很方便的办法。

怎么做?​

下面的CSP设置使得Electron只能执行自身站点和来自apis.example.com的脚本。

// 不推荐
Content-Security-Policy: '*'

// 推荐
Content-Security-Policy: script-src 'self' https://apis.example.com

CSP HTTP headers​

Electron 遵循 Content-Security-Policy HTTP 头部,可以使用 Electron 的 webRequest.onHeadersReceived 处理函数来设置这个头部:

main.js (Main Process)
const { session } = require('electron')

session.defaultSession.webRequest.onHeadersReceived((details, callback) => {
callback({
responseHeaders: {
...details.responseHeaders,
'Content-Security-Policy': ['default-src \'none\'']
}
})
})

注意:仅当调用了 app.whenReady 后才能使用 session.defaultSession 。

CSP meta tag​

CSP 的首选传输机制是一个 HTTP 头. 但是, 使用 file:// 协议加载资源时,无法使用此方法。 在某些情况下,使用 <meta> 标记直接在标记(makeup)中对页面设置策略 很有用:

index.html (Renderer Process)
<meta http-equiv="Content-Security-Policy" content="default-src 'none'">

8. 不要设置 allowRunningInsecureContent 为 true​

info

此建议是 Electron 的默认值。

默认情况下,Electron不允许网站在HTTPS中加载或执行非安全源(HTTP) 中的脚本代码、CSS或插件。 将allowRunningInsecureContent属性设为true将禁用这种保护。

当网站的初始内容通过HTTPS加载并尝试在子请求中加载HTTP的资源时,这被称为"混合内容"。

为什么?​

通过HTTPS加载会将该资源进行加密传输,以保证其真实性和完整性。 参看只显示安全内容这节以获得更多信息。

怎么做?​

main.js (Main Process)
// 不推荐
const mainWindow = new BrowserWindow({
webPreferences: {
allowRunningInsecureContent: true
}
})
main.js (Main Process)
// 推荐
const mainWindow = new BrowserWindow({})

9. 不要开启实验性功能​

info

此建议是 Electron 的默认值。

Electron 的熟练用户可以通过 experimentalFeatures 属性来启用 Chromium 实验性功能。

为什么?​

如名称所示,实验性功能是实验性的,尚未对所有 Chromium 用户启用。 此外,它们对整个 Electron 的影响很可能没有经过测试。

尽管存在合理的使用场景,但是除非你知道你自己在干什么,否则你不应该开启这个属性。

怎么做?​

main.js (Main Process)
// 不推荐
const mainWindow = new BrowserWindow({
webPreferences: {
experimentalFeatures: true
}
})
main.js (Main Process)
// 推荐
const mainWindow = new BrowserWindow({})

10. 不要使用enableBlinkFeatures​

info

此建议是 Electron 的默认值。

Blink是Chromium里的渲染引擎名称。 就像experimentalFeatures一样,enableBlinkFeatures属性将使开发者启用被默认禁用的特性。

为什么?​

通常来说,某个特性默认不被开启肯定有其合理的原因。 针对特定特性的合理使用场景是存在的。 作为开发者,你应该非常明白你为何要开启它,有什么后果,以及对你应用安全性的影响。 在任何情况下都不应该推测性的开启特性。

怎么做?​

main.js (Main Process)
// 不推荐
const mainWindow = new BrowserWindow({
webPreferences: {
enableBlinkFeatures: 'ExecCommandInJavaScript'
}
})
main.js (Main Process)
// 推荐
const mainWindow = new BrowserWindow()

11. 不要在 WebViews 中使用 allowpopups​

info

此建议是 Electron 的默认值。

如果你正在使用 <webview>,你也许需要通过 <webview> 标签里加载的页面和代码来打开新窗口。 设置 allowpopups 属性能允许窗口使用 window.open() 方法创建新的 BrowserWindow 。 否则, <webview> 标签内不允许创建新窗口。

为什么?​

如果你不需要弹出窗口,你最好在默认情况下不允许创建新的 BrowserWindow 。 以下是最低的权限要求原则:若非必要,不要再网站中创建新窗口。

怎么做?​

index.html (Renderer Process)
<!-- 不推荐 -->
<webview allowpopups src="page.html"></webview>

<!-- 推荐 -->
<webview src="page.html"></webview>

12. 创建WebView前确认其选项​

通过渲染进程创建的WebView是不开启Node.js集成的,且也不能由自身开启。 但是,WebView可以通过其webPreferences属性创建一个独立的渲染进程。

在主进程中,对 <webview> 标签的创建进行控制,并确认其 webPreferences 没有禁用安全特性是个不错的办法。

为什么?​

由于 <webview> 存在在DOM中,因此即使Node继承被禁用,它也可以通过运行在您的 网站上的脚本创建它们。

Electron 可以让开发者关闭各种控制渲染进程的安全特性。 通常情况下,开发者并不需要关闭他们中的任何一种 - 因此你不应该允许新创建的 <webview> 标签具有不同的配置。

怎么做?​

在 <webview> 标签生效前,Electron 将触发 webContents 的 will-attach-webview 事件。 利用这个事件来阻止可能含有不安全选项的 webViews 创建。

main.js (Main Process)
app.on('web-contents-created', (event, contents) => {
contents.on('will-attach-webview', (event, webPreferences, params) => {
// 如果未使用,则删除预加载脚本或验证其位置是否合法
delete webPreferences.preload

// 禁用 Node.js 集成
webPreferences.nodeIntegration = false

// 验证正在加载的 URL
if (!params.src.startsWith('https://example.com/')) {
event.preventDefault()
}
})
})

同样,这个清单只是将风险降低到最低限度,但没有将其消除。 如果您的目标是展示一个网站,浏览器将是一个更安全的选择。

13. 禁用或限制网页跳转​

如果你的应用不需要导航或只需要导航到已知页面,最好将导航完全限制在该已知范围内,不允许任何其他类型的导航。

为什么?​

导航是一种常见的攻击媒介。 如果攻击者可以诱使你的应用导航离开其当前页面,则他们可能会强制你的应用在 Internet 上打开网站。 即使你的webContents被配置为增强安全(如禁用nodeIntegration或启用contextIsolation),让你的应用打开一个任意的网站依旧是非常简单的操作。

一种常见的攻击模式是,攻击者诱导你的应用的用户与此应用进行能够使其导航到攻击者的某个页面的互动。 这通常是通过链接、插件或其他用户生成的内容完成的。

怎么做?​

如果您的应用不需要跳转,您可以在 will-navigate 处理函数中调用 event.preventDefault()。 如果您知道您的应用程序可能会导航到哪些界面,请在事件处理器中检查URL,并且仅当它与您预期的URL匹配时才进行导航。

我们建议您使用Node的解析器来处理URL。 简单的字符串比较有时会出错 - startsWith('https://example.com')测试会让https://example.com.attacker.com通过.

main.js (Main Process)
const { app } = require('electron')

const { URL } = require('node:url')

app.on('web-contents-created', (event, contents) => {
contents.on('will-navigate', (event, navigationUrl) => {
const parsedUrl = new URL(navigationUrl)

if (parsedUrl.origin !== 'https://example.com') {
event.preventDefault()
}
})
})

14. 禁用或限制新窗口创建​

如果您有已知的窗口组,那么限制您的应用程序创建额外的窗口是一个好主意。

为什么?​

与导航非常相似,创建新 webContents 是 一种常见的攻击方式。 攻击者试图诱使您的应用创建新的窗口、框架、 或其他渲染过程,拥有比以前更多的权限; 或 打开之前无法打开的页面。

如果您除了知道需要创建的窗口之外,还不需要创建 窗口,则禁用创建可以免费为您带来一些额外的 安全性。 对于打开一个 BrowserWindow 并且不需要在运行时打开任意数量的附加 窗口的应用来说,情况通常如此。

怎么做?​

在创建新窗口前,webContents 将调用窗口打开处理函数。 除其他参数外,处理程序 将接收请求打开窗口的 url 以及用于创建窗口的选项。 我们建议您注册一个处理程序来 监视窗口的创建,并拒绝任何意外的窗口创建。

main.js (Main Process)
const { app, shell } = require('electron')

app.on('web-contents-created', (event, contents) => {
contents.setWindowOpenHandler(({ url }) => {
// 在这个例子中,我们要求操作系统
// 在默认浏览器中打开此事件的 URL
//
// 关于哪些URL应该被允许通过shell.openExternal打开,
// 请参照以下项目。
if (isSafeForExternalOpen(url)) {
setImmediate(() => {
shell.openExternal(url)
})
}

return { action: 'deny' }
})
})

15. 不要对不可信的内容使用 shell.openExternal​

shell 模块的 openExternal API 能让你使用桌面原生程序打开指定的协议 URI。 例如,在 macOS 上,此功能与 open 终端命令实用程序类似,将基于 URI 和文件类型关联打开特定的应用程序。

为什么?​

不正确使用 openExternal 可能会危及用户的主机。 当 openExternal 使用内容不受信任时,它可以用来执行任意命令。

怎么做?​

main.js (Main Process)
// 不推荐
const { shell } = require('electron')

shell.openExternal(USER_CONTROLLED_DATA_HERE)
main.js (Main Process)
// 推荐
const { shell } = require('electron')

shell.openExternal('https://example.com/index.html')

16. 使用当前版本的 Electron​

你应该努力始终去使用最新版本的 Electron。 每当发布新的主要版本时,你应该尝试尽快更新您的应用。

为什么?​

一个使用 Electron、Chromium 和 Node.js 的旧版本构建的应用程序比使用这些组件的最新版本的应用程序更容易成为目标。 一般来说,较旧的 版本的 Chromium 和 Node.js 的安全问题和漏洞利用更多。

Chromium 和 Node.js 都是数千名有才华的开发者建造的令人印象深刻的工程。 鉴于他们受欢迎的程度,他们的安全性都经过专业的安全研究人员仔细的测试和分析。 其中许多研究人员都会负责任地披露漏洞,这通常意味着研究人员会给 Chromium 和 Node.js 一些时间来修复问题,然后再将其公布。 如果你的应用程序运行的是 Electron 的最新版本 (包括 Chromium 和 Node.js),你的应用程序将更加安全,因为潜在的安全问题并不广为人知。

怎么做?​

一次仅迁移一个主要版本,并查阅 Electron 的破坏性更改文档以了解是否有代码需要更新。

17. 验证所有 IPC 消息的 sender​

应始终验证传入的 IPC 消息的 sender 属性,确保 未使用不受信任的渲染器执行动作或向不受信任的渲染器发送信息。

为什么?​

从理论上讲,所有 Web Frame 都可以将 IPC 消息发送到主进程,包括在某些情况下 iframe 和子窗口。 如果您的 IPC 消息通过 event.reply 向发件人返回 用户数据,或者执行了渲染器 无法本机执行的特权操作,则应确保您没有侦听第三方 web frame。

您应该默认验证 所有 IPC 消息 sender 。

怎么做?​

main.js (Main Process)
// 不推荐
ipcMain.handle('get-secrets', () => {
return getSecrets()
})

// 推荐
ipcMain.handle('get-secrets', (e) => {
if (!validateSender(e.senderFrame)) return null
return getSecrets()
})

function validateSender (frame) {
// Validate the host of the URL using an actual URL parser and an allowlist
if ((new URL(frame.url)).host === 'electronjs.org') return true
return false
}

18. 不要使用 file://,而是使用自定义协议​

您应该使用自定义协议提供本地页面,而非 file:// 协议。

为什么?​

相较于网络浏览器,file:// 协议在 Electron 中将获得更多权限。即使是在浏览器中,它的处理方式也与 http/https URL 不同。 使用自定义协议更加符合经典的网络 URL 行为,同时能更好地控制加载的内容和时机。

在 file:// 上运行的页面可以单方面访问你机器上的每个文件,这意味着可以利用 XSS 问题加载用户机器上的任意文件。 使用自定义协议可以防止这类问题,因为您可以将协议限制为只为特定的一组文件提供服务。

怎么做?​

通过 protocol.handle 里的例子可以学习如何通过自定义协议提供文件/内容。

19. 检查你可以修改哪些 Fuse​

Electron 提供了很多有用的选项,但是很大一部分的应用程序很可能不需要这些选项。 为避免需要自行构建您自己的 Electron 版本,您可以使用 Fuse 来关闭或打开这些选项。

为什么?​

有些 Fuse,比如 runAsNode 和 nodeCliInspect,允许应用程序在通过命令行运行时,根据特定环境变量或命令行参数产生不同的行为。 它们可以用来通过您的应用程序在设备上执行命令。

这会允许外部脚本运行其本不被允许,但您的应用程序又有权力运行的命令。

怎么做?​

@electron/fuses 是我们制作的一个模块,可以用来轻松翻转这些 Fuse。 要了解使用方法以及潜在的错误用法,请参阅该模块的 README 并参考我们文档的我该如何翻转 Fuse?

20. 请勿将 Electron API 暴露给不受信任的网络内容​

您不应直接暴露 Electron 的 API(特别是 IPC)给预加载脚本中的不受信任的网页内容。

为什么?​

暴露像 ipcRenderer.on 那样的原始 API 是危险的,因为它给予了渲染进程直接访问整个 IPC 事件系统的权限,允许他们监听任意 IPC 事件,而不仅仅是为他们设计的事件。

为了避免这种暴露,我们也无法直接传递回调函数:IPC 事件回调函数的第一个参数是一个 IpcRendererEvent 对象,其中包含诸如 sender 之类的属性,这些属性提供了对底层 ipcRenderer 实例的访问权限。 即使您只监听特定的事件,直接传递回调函数也意味着渲染进程会获得对该事件对象的访问权限。

简而言之,我们希望不受信任的网页内容只能访问必要的信息和 API。

怎么做?​

preload
// 不推荐
contextBridge.exposeInMainWorld('electronAPI', {
on: ipcRenderer.on
})

// 同样不推荐
contextBridge.exposeInMainWorld('electronAPI', {
onUpdateCounter: (callback) => ipcRenderer.on('update-counter', callback)
})

// 推荐
contextBridge.exposeInMainWorld('electronAPI', {
onUpdateCounter: (callback) => ipcRenderer.on('update-counter', (_event, value) => callback(value))
})
info

有关什么是 contextIsolation 以及如何用它来保障应用安全的信息,请参阅上下文隔离文档。