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
+17 -7
View File
@@ -97,6 +97,10 @@ export const MAIN_DIST = path.join(process.env.APP_ROOT, "dist-electron");
export const RENDERER_DIST = path.join(process.env.APP_ROOT, "dist");
export const VITE_DEV_SERVER_URL = process.env.VITE_DEV_SERVER_URL;
// 进程专属临时目录,避免多实例/残留进程互相影响
// 退出时由 will-quit 统一清理
export const TEMP_BASE = path.join(os.tmpdir(), `spark-store-${process.pid}`);
process.env.VITE_PUBLIC = VITE_DEV_SERVER_URL
? path.join(process.env.APP_ROOT, "public")
: RENDERER_DIST;
@@ -311,7 +315,12 @@ function isVisible(bounds: WindowState): boolean {
// 解构为局部常量后,控制流收窄(const 不可变)可穿透到下方嵌套闭包,
// 消除 x/y/width/height 的 “可能为未定义” 告警
const { x, y, width, height } = bounds;
if (x === undefined || y === undefined || width === undefined || height === undefined) {
if (
x === undefined ||
y === undefined ||
width === undefined ||
height === undefined
) {
return false;
}
const displays = screen.getAllDisplays();
@@ -327,9 +336,7 @@ function loadWindowState(): WindowState {
try {
const file = getWindowStatePath();
if (fs.existsSync(file)) {
const parsed = JSON.parse(
fs.readFileSync(file, "utf-8"),
) as WindowState;
const parsed = JSON.parse(fs.readFileSync(file, "utf-8")) as WindowState;
if (
parsed.width !== undefined &&
parsed.height !== undefined &&
@@ -400,7 +407,10 @@ async function createWindow() {
: Math.max(saved.width ?? DEFAULT_WINDOW_SIZE.width, MIN_WINDOW_SIZE.width);
const restoredHeight = oversized
? DEFAULT_WINDOW_SIZE.height
: Math.max(saved.height ?? DEFAULT_WINDOW_SIZE.height, MIN_WINDOW_SIZE.height);
: Math.max(
saved.height ?? DEFAULT_WINDOW_SIZE.height,
MIN_WINDOW_SIZE.height,
);
const mainWindow = new BrowserWindow({
title: "星火应用商店",
@@ -663,9 +673,9 @@ app.on("activate", () => {
});
app.on("will-quit", () => {
// Clean up temp dir
// 清理本进程专属临时目录(PID 隔离,不影响其他实例)
logger.info("Cleaning up temp dir");
fs.rmSync("/tmp/spark-store/", { recursive: true, force: true });
fs.rmSync(TEMP_BASE, { recursive: true, force: true });
logger.info("Done, exiting");
});