Conversation
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 文件类型
✅ CI 检查通过本次 PR 已完成以下自动检查:
由 pull_request test workflow 自动生成 |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
这里的 axios request 拦截器错误分支没有 return,会导致拦截器回调返回 undefined(axios 可能继续执行并在后续使用到无效 config),从而引发不可预期的请求失败/异常。建议改为 return Promise.reject(error)(或直接 throw error)以确保链路正确进入 reject 流程。
| Promise.reject(error) | |
| return Promise.reject(error) |
| openUrl: (url) => invokePrefixed('open-url', url), | ||
| openSpecifiedFile: (targetPath) => invokePrefixed('open-specified-file', targetPath), | ||
| openRemoteLink: () => invokePrefixed('open-remote-link'), | ||
| openYakitPath: () => invokePrefixed('open-yaklang-path'), |
There was a problem hiding this comment.
openYakitPath 映射到的 channel 是 open-yaklang-path,但本 PR 里 engine-link-startup 的更新提示从 open-yakit-path 迁移为 yakitShell.openYakitPath();这会造成 channel 不一致而在运行时调用失败。建议统一命名/映射:要么这里改为调用 invokePrefixed('open-yakit-path'),要么将渲染侧方法名/调用点同步改为 openYaklangPath(并与主进程已注册的 handler 保持一致)。
| openYakitPath: () => invokePrefixed('open-yaklang-path'), | |
| openYakitPath: () => invokePrefixed('open-yakit-path'), |
| throw new Error('absolute urls are not allowed') | ||
| } | ||
|
|
||
| return trimmed.replace(/^\/+/, '') |
There was a problem hiding this comment.
normalizeRelativeApiPath 目前只禁止绝对 URL,但未禁止包含 .. 的路径(例如 ../auth/user)。在 app/main/api/index.js 中会把该值拼到 ${baseUrl}/api/ 后面,从而可能通过 /api/../xxx 逃逸到非预期的后端路径。建议显式拒绝包含 ..(以及反斜杠 \\)的路径片段,或对 pathname 做标准化并确保最终仍在 /api/ 前缀下。
| 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 |
| ipcMain.handle('start-local-yaklang-engine', async (e, params) => { | ||
| if (!params['port']) { | ||
| throw Error('启动本地引擎必须指定端口') | ||
| } | ||
| return await asyncStartLocalYakEngineServer(win, params) | ||
| }) |
There was a problem hiding this comment.
该 IPC handler 涉及启动本地引擎进程,属于高风险能力,但这里没有调用 assertTrustedAppSender(本文件已引入该方法)。建议在 handler 开头增加 sender 校验(并对 params 做必要的白名单/类型校验),以避免不可信渲染上下文触发本地进程启动。
| ipcMain.handle('ps-yak-grpc', async (e, params) => { | ||
| if (isWindows) { | ||
| return await fetchWindowsYakProcess() | ||
| } else { | ||
| return await fetchGeneralYakProcess() | ||
| } | ||
| }) |
There was a problem hiding this comment.
ps-yak-grpc 会向渲染进程暴露本机进程信息(pid/cmd/port 等),但此处未做 assertTrustedAppSender 校验;同文件中 kill-yak-grpc 已加校验,建议对该枚举类接口同样增加 sender 信任校验,避免被非可信渲染端探测本机进程信息。
| 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}`) | ||
| }) | ||
| }) | ||
| } |
There was a problem hiding this comment.
runWindowsTaskKill 在 yakLocal.js 与 engineStatus.js 中存在重复实现(几乎相同的 spawn/close/stderr 逻辑)。建议抽到一个共享模块(例如 app/main/security.js 或 app/main/utils/process.js),统一维护,避免后续修复(比如编码、stdio、错误信息格式)时出现行为不一致。