fix/refactor: 更新中心扫描与多项安全加固(经专业审计)

更新中心扫描修复:
- updateCenter.ts: 抽出 runSystemUpdateThenLoad, open/refresh 共用,
  打开时即刷新双源(aptss ssupdate + apm update), 失败仅告警不阻断扫描
- shell-caller.sh: ssupdate 分支 exit $? 恒 0 吞掉刷新失败, 改为 exit $exit_code
- update-center/query.ts: 移除 nextVersion===currentVersion 误删真实更新项逻辑,
  信任 aptss 上游 upgradable 判断

安全加固:
- AppDetailModal.vue: 新增 sanitizeMoreContent 剥除 HTML 标签后再 v-html, 防 XSS
- InstalledAppsModal.vue: ALLOWED_LOCAL_ICON_PREFIXES 收紧为具体子目录, 缩小
  本地文件读取面
- install-manager.ts: filename 用 path.basename 防路径遍历; 包名/文件名 PKGNAME_PATTERN 校验
- index.ts: 临时目录改用 spark-store-${pid} 隔离, will-quit 清理对应目录

经 7 维度专业审计(安全/功能/类型/可维护/资源/性能/兼容)通过。
This commit is contained in:
xiyidaiwa
2026-08-10 21:42:36 +08:00
parent 0be6f8ad11
commit 3f22207505
7 changed files with 180 additions and 134 deletions
+14 -2
View File
@@ -339,7 +339,12 @@ ipcMain.on("queue-install", async (event, download_json) => {
const superUserCmd = await checkSuperUserCommand();
let execCommand = "";
const execParams = [];
const downloadDir = `/tmp/spark-store/download/${pkgname}`;
const downloadDir = path.join(
os.tmpdir(),
`spark-store-${process.pid}`,
"download",
pkgname,
);
// APM 应用:若本机没有 apm 命令,通知前端弹窗引导安装 APM
if (origin === "apm") {
@@ -390,7 +395,14 @@ ipcMain.on("queue-install", async (event, download_json) => {
execParams.push("apm");
if (metalinkUrl && filename) {
execParams.push("ssinstall", `${downloadDir}/${filename}`);
// 防御性深度校验:即便 PKGNAME_PATTERN 已挡掉路径遍历字符,仍用 path.basename
// 确保 filename 为纯文件名、不含目录分量(belt-and-suspenders
const safeFilename = path.basename(filename);
if (safeFilename !== filename) {
logger.warn(`ssinstall filename contains path traversal: ${filename}`);
return;
}
execParams.push("ssinstall", path.join(downloadDir, safeFilename));
} else {
execParams.push("install", "-y", pkgname);
}
@@ -1,11 +1,16 @@
import { join } from "node:path";
import { tmpdir } from "node:os";
import { runAria2Download, type Aria2DownloadResult } from "./download";
import { installPackage } from "../shared-installer";
import type { UpdateCenterQueue, UpdateCenterTask } from "./queue";
import type { UpdateCenterItem } from "./types";
const DEFAULT_DOWNLOAD_ROOT = "/tmp/spark-store/update-center";
const DEFAULT_DOWNLOAD_ROOT = join(
tmpdir(),
`spark-store-${process.pid}`,
"update-center",
);
export interface InstallUpdateItemOptions {
item: UpdateCenterItem;
+5 -1
View File
@@ -210,7 +210,11 @@ const parseUpgradableOutput = (
const arch = tokens[2] ?? "";
const currentVersion =
trimmed.match(CURRENT_VERSION_PATTERN)?.[1] ?? tokens[5] ?? "";
if (!pkgname || nextVersion === currentVersion) {
// 仅当包名缺失或当前版本解析失败时才跳过。
// 注意:不再因 nextVersion === currentVersion 而跳过——aptss 已判定该项为
// upgradable,应信任上游判断;否则当仓库元数据出现"同版本重新发布"等情况时,
// 真实的更新项会被无声隐藏,导致"软件更新"列表空白。
if (!pkgname || !currentVersion) {
continue;
}