diff --git a/electron/main/backend/install-manager.ts b/electron/main/backend/install-manager.ts index 02bea18e..4f8e2a40 100644 --- a/electron/main/backend/install-manager.ts +++ b/electron/main/backend/install-manager.ts @@ -297,6 +297,16 @@ ipcMain.on("queue-install", async (event, download_json) => { return; } + // 包名/文件名白名单校验:防止路径遍历(如 ../../)或非法字符进入下载目录与安装命令构建 + if (!PKGNAME_PATTERN.test(pkgname)) { + logger.warn(`queue-install invalid pkgname: ${pkgname}`); + return; + } + if (filename && !PKGNAME_PATTERN.test(filename)) { + logger.warn(`queue-install invalid filename: ${filename}`); + return; + } + logger.info(`收到下载任务: ${id}, 软件包名称: ${pkgname}, 来源: ${origin}`); const webContents = event.sender; diff --git a/src/App.vue b/src/App.vue index 3e82745d..b98d945b 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1380,13 +1380,17 @@ const loadHome = async () => { if (!url) continue; const icon = (l.Icon as string) || (l.icon as string) || ""; seenNames.add(name); - homeLinks.value.push({ - ...l, + // 显式提取已知字段构造,避免通过展开运算符 { ...l } 把远程不可信数据中的未知属性注入响应式状态 + const safeLink: HomeLink = { name, url, icon, + more: (l.more as string) || undefined, + imgUrl: (l.imgUrl as string) || undefined, + type: (l.type as string) || undefined, origin: mode, - } as HomeLink); + }; + homeLinks.value.push(safeLink); } } } catch (e) {