Skip to content

feat: 增加安全性检查和改进 IPC 处理#3582

Open
Go0p wants to merge 1 commit intomasterfrom
go0p/security/renderer-hardening
Open

feat: 增加安全性检查和改进 IPC 处理#3582
Go0p wants to merge 1 commit intomasterfrom
go0p/security/renderer-hardening

Conversation

@Go0p
Copy link
Copy Markdown
Collaborator

@Go0p Go0p commented Apr 9, 2026

  • 在多个 IPC 处理函数中添加了对发送者的信任检查
  • 引入了新的安全模块以规范化 HTTP URL 和验证打开路径
  • 更新了 engineLinkPreload.js 和 httpServer.js 以支持新的安全功能
  • 在用户信息处理和动态控制功能中增强了错误处理和参数验证
  • 更新了 yarn.lock 以包含 axios 依赖的最新版本
  • 将 .gitignore 中添加了 .serena 文件类型

- 在多个 IPC 处理函数中添加了对发送者的信任检查
- 引入了新的安全模块以规范化 HTTP URL 和验证打开路径
- 更新了 engineLinkPreload.js 和 httpServer.js 以支持新的安全功能
- 在用户信息处理和动态控制功能中增强了错误处理和参数验证
- 更新了 yarn.lock 以包含 axios 依赖的最新版本
- 将 .gitignore 中添加了 .serena 文件类型
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 9, 2026

✅ CI 检查通过

本次 PR 已完成以下自动检查:

  • ✅ i18n 配置校验通过(zh/en)
  • ✅ Prettier 格式化已完成
  • ✅ 结果已自动提交到当前 PR 分支(如有变更)

由 pull_request test workflow 自动生成

@hjhke hjhke requested a review from Copilot April 10, 2026 09:28
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

该 PR 主要将渲染进程的 Electron IPC 调用迁移到统一的 electronBridge 接口,并在主进程侧补齐 IPC 发送方信任校验与 URL/路径规范化,降低被非可信渲染端滥用 IPC 的风险。

Changes:

  • 渲染端:将大量 ipcRenderer.invoke/on 改为 @/services/electronBridge(以及 engine-link-startup 的本地 bridge)封装调用,并调整事件订阅的清理方式
  • 主进程:新增 security.js,在多个 IPC handler 中引入 assertTrustedAppSender 与 URL/路径校验(含 axios-api 参数净化)
  • 引擎联动启动页:新增/替换 engine-link-startup 的 bridge 访问方式,并将相关工具函数迁移到此 bridge

Reviewed changes

Copilot reviewed 61 out of 104 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
app/renderer/src/main/src/components/layout/utils.ts 将项目导出/上传等 IPC 调用替换为 electronBridge 封装
app/renderer/src/main/src/components/layout/update/UpdateYakitAndYaklang.tsx 更新/下载流程改用 yakitEngine/yakitShell/yakitWindowControls,改进事件订阅清理
app/renderer/src/main/src/components/layout/update/DownloadYaklang.tsx Yak 引擎下载/安装改用 yakitEngine,替换 progress 事件监听方式
app/renderer/src/main/src/components/layout/update/DownloadYakit.tsx 软件包下载改用 yakitEngine/yakitShell,替换 progress 事件监听方式
app/renderer/src/main/src/components/layout/hooks/useMcp/useMcp.ts MCP 流式 IPC 改用 yakitStream/yakitMcp,完善 off/cleanup
app/renderer/src/main/src/components/layout/hooks/useEngineConsole/useEngineConsole.ts 控制台流式输出改为 yakitStream,并将主题/窗口通信迁移到 yakitWindow
app/renderer/src/main/src/components/layout/YaklangEngineWatchDog.tsx 引擎连接/启动/端口检测迁移到 yakitEngine
app/renderer/src/main/src/components/layout/YakitGlobalHost.tsx 获取引擎连接地址迁移到 yakitEngine.fetchYaklangEngineAddr
app/renderer/src/main/src/components/layout/WinUIOp.tsx 窗口控制与 kill run node 改用 bridge 封装
app/renderer/src/main/src/components/layout/WelcomeConsoleUtil.tsx 欢迎页日志输出与 Echo 检测迁移到 yakitEngine
app/renderer/src/main/src/components/layout/MacUIOp.tsx macOS 窗口控制与 kill run node 改用 bridge 封装
app/renderer/src/main/src/components/layout/HelpDoc/HelpDoc.tsx 外链打开从 IPC 迁移到 yakitShell.openExternal
app/renderer/src/main/src/components/layout/EngineLog.tsx 引擎日志监听迁移到 yakitLogs,改进事件清理
app/renderer/src/main/src/components/layout/AllKillEngineConfirm.tsx 引擎进程枚举/kill 改用 yakitEngine
app/renderer/src/main/src/components/baseConsole/BaseConsole.tsx 控制台流式输出与系统信息获取迁移到 bridge 封装
app/renderer/src/main/src/components/ConfigPrivateDomain/ConfigPrivateDomain.tsx 私有域设置/鉴权/编解码等迁移到 yakitAuth/yakitProfile/yakitCodec/yakitUILayout
app/renderer/src/main/src/components/BaseTitleBar/index.tsx 子窗口最小化/最大化/关闭迁移到 yakitChildWindow
app/renderer/src/main/src/apiUtils/http.ts 上传相关 IPC 迁移到 yakitUpload
app/renderer/src/main/src/apiUtils/grpc.ts 多个引擎相关 IPC 迁移到 yakitEngine
app/renderer/src/main/src/NewApp.tsx 启动流程、退出/最小化事件、socket 启停、同步 baseUrl/user 等迁移到 bridge 封装
app/renderer/engine-link-startup/src/utils/openWebsite.tsx 引擎联动启动页打开文件改用 startup bridge
app/renderer/engine-link-startup/src/utils/logCollection.ts 引擎联动启动页日志目录打开/主动日志输出改用 startup bridge
app/renderer/engine-link-startup/src/utils/kv.tsx 引擎联动启动页 KV 存取改用 startup bridge
app/renderer/engine-link-startup/src/utils/electronBridge.ts 新增:engine-link-startup 侧的 yakitBridge 访问封装
app/renderer/engine-link-startup/src/utils/clipboard.ts 引擎联动启动页剪贴板读写改用 startup bridge
app/renderer/engine-link-startup/src/pages/StartupPage/utils.ts 启动页系统信息/欢迎日志输出迁移到 startup bridge
app/renderer/engine-link-startup/src/pages/StartupPage/components/YaklangEngineWatchDog/index.tsx 启动页引擎连接改用 startup bridge
app/renderer/engine-link-startup/src/pages/StartupPage/components/UpdateYakitHint/index.tsx 启动页更新下载 UI 改用 startup bridge
app/renderer/engine-link-startup/src/pages/StartupPage/components/UIEngineList/index.tsx 启动页进程列表/kill/切换引擎改用 startup bridge
app/renderer/engine-link-startup/src/pages/StartupPage/components/PerformanceDisplay/index.tsx 启动页性能采样改用 startup bridge
app/renderer/engine-link-startup/src/pages/StartupPage/components/HelpDoc/index.tsx 启动页外链打开改用 startup bridge
app/renderer/engine-link-startup/src/pages/StartupPage/components/EngineLog/index.tsx 启动页日志流监听改用 startup bridge
app/renderer/engine-link-startup/src/pages/StartupPage/components/DownloadYaklang/index.tsx 启动页下载进度监听改用 startup bridge
app/renderer/engine-link-startup/src/hooks/useTheme.ts 启动页主题监听改用 startup bridge,避免重复注册
app/renderer/engine-link-startup/src/App.tsx 启动页 ready/退出处理迁移到 startup bridge
app/main/uiOperate/other.js 主进程外链/文件路径类 IPC 增加 sender 信任校验与 URL 规范化
app/main/security.js 新增:主进程安全工具(sender 校验、URL 规范化、路径校验、PID 规范化等)
app/main/newUiOperate/other.js 新 IPC 前缀版 open-url 增加 sender 校验与 URL 规范化
app/main/httpServer.js baseUrl 同步与 axios 拦截增强:sender 校验、baseUrl 规范化与错误信息改进
app/main/handlers/yakLocal.js kill/ps 相关能力引入 sender 校验与 PID 规范化,改进 Windows taskkill 执行
app/main/handlers/userInfo.js 登录流程增加 sender 校验与登录 URL 白名单/规范化,强化 BrowserWindow 安全配置
app/main/handlers/openWebsiteByChrome.js 打开外链/路径引入 sender 校验、URL 规范化与路径校验
app/main/handlers/engineStatus.js 引擎启动/kill 节点等能力部分引入 sender 校验与 PID 规范化
app/main/handlers/dynamicControlFun.js 动态控制启动命令改用 spawn 传参,避免拼接命令字符串问题
app/main/engineLinkPreload.js 将 EngineLink 窗口 preload 改为 contextBridge 暴露 yakitBridge,并封装订阅/调用
app/main/api/index.js axios-api IPC 增加 sender 校验与请求参数净化(禁止自定义 baseURL/agent/adapter 等)

return config
},
(error) => {
Promise.reject(error)
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里的 axios request 拦截器错误分支没有 return,会导致拦截器回调返回 undefined(axios 可能继续执行并在后续使用到无效 config),从而引发不可预期的请求失败/异常。建议改为 return Promise.reject(error)(或直接 throw error)以确保链路正确进入 reject 流程。

Suggested change
Promise.reject(error)
return Promise.reject(error)

Copilot uses AI. Check for mistakes.
openUrl: (url) => invokePrefixed('open-url', url),
openSpecifiedFile: (targetPath) => invokePrefixed('open-specified-file', targetPath),
openRemoteLink: () => invokePrefixed('open-remote-link'),
openYakitPath: () => invokePrefixed('open-yaklang-path'),
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

openYakitPath 映射到的 channel 是 open-yaklang-path,但本 PR 里 engine-link-startup 的更新提示从 open-yakit-path 迁移为 yakitShell.openYakitPath();这会造成 channel 不一致而在运行时调用失败。建议统一命名/映射:要么这里改为调用 invokePrefixed('open-yakit-path'),要么将渲染侧方法名/调用点同步改为 openYaklangPath(并与主进程已注册的 handler 保持一致)。

Suggested change
openYakitPath: () => invokePrefixed('open-yaklang-path'),
openYakitPath: () => invokePrefixed('open-yakit-path'),

Copilot uses AI. Check for mistakes.
throw new Error('absolute urls are not allowed')
}

return trimmed.replace(/^\/+/, '')
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

normalizeRelativeApiPath 目前只禁止绝对 URL,但未禁止包含 .. 的路径(例如 ../auth/user)。在 app/main/api/index.js 中会把该值拼到 ${baseUrl}/api/ 后面,从而可能通过 /api/../xxx 逃逸到非预期的后端路径。建议显式拒绝包含 ..(以及反斜杠 \\)的路径片段,或对 pathname 做标准化并确保最终仍在 /api/ 前缀下。

Suggested change
return trimmed.replace(/^\/+/, '')
if (trimmed.includes('\\')) {
throw new Error('backslashes are not allowed in url paths')
}
const normalized = trimmed.replace(/^\/+/, '')
const segments = normalized.split('/')
if (segments.some((segment) => segment === '.' || segment === '..')) {
throw new Error('path traversal segments are not allowed')
}
return normalized

Copilot uses AI. Check for mistakes.
Comment on lines +208 to +213
ipcMain.handle('start-local-yaklang-engine', async (e, params) => {
if (!params['port']) {
throw Error('启动本地引擎必须指定端口')
}
return await asyncStartLocalYakEngineServer(win, params)
})
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

该 IPC handler 涉及启动本地引擎进程,属于高风险能力,但这里没有调用 assertTrustedAppSender(本文件已引入该方法)。建议在 handler 开头增加 sender 校验(并对 params 做必要的白名单/类型校验),以避免不可信渲染上下文触发本地进程启动。

Copilot uses AI. Check for mistakes.
Comment on lines +272 to +278
ipcMain.handle('ps-yak-grpc', async (e, params) => {
if (isWindows) {
return await fetchWindowsYakProcess()
} else {
return await fetchGeneralYakProcess()
}
})
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ps-yak-grpc 会向渲染进程暴露本机进程信息(pid/cmd/port 等),但此处未做 assertTrustedAppSender 校验;同文件中 kill-yak-grpc 已加校验,建议对该枚举类接口同样增加 sender 信任校验,避免被非可信渲染端探测本机进程信息。

Copilot uses AI. Check for mistakes.
Comment on lines +45 to 66
const runWindowsTaskKill = (pid) => {
return new Promise((resolve, reject) => {
const subprocess = childProcess.spawn('taskkill', ['/F', '/PID', `${pid}`], {
windowsHide: true,
stdio: ['ignore', 'ignore', 'pipe'],
})
let stderr = ''
subprocess.stderr.on('data', (data) => {
stderr += data.toString('utf-8')
})
subprocess.on('error', (error) => {
reject(error)
})
subprocess.on('close', (code) => {
if (code === 0) {
resolve('')
return
}
reject(stderr || `taskkill exited with code ${code}`)
})
})
}
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

runWindowsTaskKillyakLocal.jsengineStatus.js 中存在重复实现(几乎相同的 spawn/close/stderr 逻辑)。建议抽到一个共享模块(例如 app/main/security.jsapp/main/utils/process.js),统一维护,避免后续修复(比如编码、stdio、错误信息格式)时出现行为不一致。

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants