fix(security/robustness): 清理 update-center 调试日志 + cancel-install id 校验

- update-center/index.ts: 引入 pino logger,将约 30 处 console.log(含 [DEBUG] 前缀及敏感路径)
  替换为 logger.debug(生产默认 info 级不打印,消除敏感信息泄露)
- install-manager.ts: cancel-install 增加 id 整数类型校验(typeof number && isInteger),防御非法输入
- PR 审查其余 5 项经代码实证为误报:JSON.parse 已有 try-catch、activeDownloadCount 的 mkdir/axios
  均在 try 内且 finally 必执行、check/remove-installed 已用 parseAppPayload 做 PKGNAME_PATTERN 校验、
  origin 已枚举归一化、initializeUpdateCenter 已有单例守卫;async handler 顶层 try-catch 因 Electron
  主进程默认 unhandledRejection 不崩溃且改动面大(19 handler)风险高,未改
This commit is contained in:
xiyidaiwa
2026-08-13 23:37:03 +08:00
parent 3cedd0c517
commit 7bad39a796
3 changed files with 34 additions and 26 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
spark-store (5.2.1.8-test) UNRELEASED; urgency=medium spark-store (5.2.1.9-test) UNRELEASED; urgency=medium
* Initial release. (Closes: #nnnn) <nnnn is the bug number of your ITP> * Initial release. (Closes: #nnnn) <nnnn is the bug number of your ITP>
+5
View File
@@ -597,6 +597,11 @@ ipcMain.on("queue-install", async (event, download_json) => {
// Cancel Handler // Cancel Handler
ipcMain.on("cancel-install", (event, id) => { ipcMain.on("cancel-install", (event, id) => {
// 防御性输入校验:id 应为整数,避免 Map 以非预期键查找导致逻辑异常
if (typeof id !== "number" || !Number.isInteger(id)) {
logger.warn(`cancel-install: invalid id type: ${typeof id}`);
return;
}
const task = tasks.get(id); const task = tasks.get(id);
if (!task) return; if (!task) return;
+28 -25
View File
@@ -1,7 +1,10 @@
import { spawn } from "node:child_process"; import { spawn } from "node:child_process";
import pino from "pino";
import { BrowserWindow, ipcMain } from "electron"; import { BrowserWindow, ipcMain } from "electron";
const logger = pino({ name: "updateCenter" });
import { SHELL_CALLER_PATH } from "../shared-installer"; import { SHELL_CALLER_PATH } from "../shared-installer";
import { findExecutable, SUPER_USER_COMMAND_CANDIDATES } from "../superuser"; import { findExecutable, SUPER_USER_COMMAND_CANDIDATES } from "../superuser";
import { import {
@@ -165,9 +168,9 @@ const loadAptssItemMetadata = async (
| { item: UpdateCenterItem; warning?: undefined } | { item: UpdateCenterItem; warning?: undefined }
| { item: null; warning: string } | { item: null; warning: string }
> => { > => {
console.log(`[DEBUG] Loading APTSS metadata for ${item.pkgname}`); logger.debug(`[DEBUG] Loading APTSS metadata for ${item.pkgname}`);
const printUrisCommand = getAptssPrintUrisCommand(item.pkgname); const printUrisCommand = getAptssPrintUrisCommand(item.pkgname);
console.log( logger.debug(
`[DEBUG] APTSS command: ${printUrisCommand.command} ${printUrisCommand.args.join(" ")}`, `[DEBUG] APTSS command: ${printUrisCommand.command} ${printUrisCommand.args.join(" ")}`,
); );
@@ -175,11 +178,11 @@ const loadAptssItemMetadata = async (
printUrisCommand.command, printUrisCommand.command,
printUrisCommand.args, printUrisCommand.args,
); );
console.log(`[DEBUG] APTSS metadata result code: ${metadataResult.code}`); logger.debug(`[DEBUG] APTSS metadata result code: ${metadataResult.code}`);
console.log( logger.debug(
`[DEBUG] APTSS metadata stdout: ${metadataResult.stdout.substring(0, 500)}`, `[DEBUG] APTSS metadata stdout: ${metadataResult.stdout.substring(0, 500)}`,
); );
console.log( logger.debug(
`[DEBUG] APTSS metadata stderr: ${metadataResult.stderr.substring(0, 500)}`, `[DEBUG] APTSS metadata stderr: ${metadataResult.stderr.substring(0, 500)}`,
); );
@@ -188,18 +191,18 @@ const loadAptssItemMetadata = async (
metadataResult, metadataResult,
); );
if (commandError) { if (commandError) {
console.log(`[DEBUG] APTSS metadata error: ${commandError}`); logger.debug(`[DEBUG] APTSS metadata error: ${commandError}`);
return { item: null, warning: commandError }; return { item: null, warning: commandError };
} }
const metadata = parsePrintUrisOutput(metadataResult.stdout); const metadata = parsePrintUrisOutput(metadataResult.stdout);
if (metadata) { if (metadata) {
console.log(`[DEBUG] APTSS parsed metadata:`, { logger.debug(`[DEBUG] APTSS parsed metadata:`, {
...metadata, ...metadata,
downloadUrl: `${metadata.downloadUrl}.metalink`, downloadUrl: `${metadata.downloadUrl}.metalink`,
}); });
} else { } else {
console.log(`[DEBUG] APTSS parsed metadata:`, metadata); logger.debug(`[DEBUG] APTSS parsed metadata:`, metadata);
} }
if (!metadata) { if (!metadata) {
@@ -378,7 +381,7 @@ export const loadUpdateCenterItems = async (
storeFilter: StoreFilter = "both", storeFilter: StoreFilter = "both",
runCommand: UpdateCenterCommandRunner = runCommandCapture, runCommand: UpdateCenterCommandRunner = runCommandCapture,
): Promise<UpdateCenterLoadItemsResult> => { ): Promise<UpdateCenterLoadItemsResult> => {
console.log( logger.debug(
`[UpdateCenter] loadUpdateCenterItems called with storeFilter=${storeFilter}`, `[UpdateCenter] loadUpdateCenterItems called with storeFilter=${storeFilter}`,
); );
const [sparkEnabled, apmEnabled] = await Promise.all([ const [sparkEnabled, apmEnabled] = await Promise.all([
@@ -389,7 +392,7 @@ export const loadUpdateCenterItems = async (
? isCommandAvailable(runCommand, "apm") ? isCommandAvailable(runCommand, "apm")
: Promise.resolve(false), : Promise.resolve(false),
]); ]);
console.log( logger.debug(
`[UpdateCenter] sparkEnabled=${sparkEnabled}, apmEnabled=${apmEnabled}`, `[UpdateCenter] sparkEnabled=${sparkEnabled}, apmEnabled=${apmEnabled}`,
); );
@@ -415,16 +418,16 @@ export const loadUpdateCenterItems = async (
: Promise.resolve({ code: 0, stdout: "", stderr: "" }), : Promise.resolve({ code: 0, stdout: "", stderr: "" }),
]); ]);
console.log( logger.debug(
`[UpdateCenter] aptssResult: code=${aptssResult.code}, stdout=${aptssResult.stdout.substring(0, 500)}, stderr=${aptssResult.stderr.substring(0, 500)}`, `[UpdateCenter] aptssResult: code=${aptssResult.code}, stdout=${aptssResult.stdout.substring(0, 500)}, stderr=${aptssResult.stderr.substring(0, 500)}`,
); );
console.log( logger.debug(
`[UpdateCenter] apmResult: code=${apmResult.code}, stdout=${apmResult.stdout.substring(0, 500)}, stderr=${apmResult.stderr.substring(0, 500)}`, `[UpdateCenter] apmResult: code=${apmResult.code}, stdout=${apmResult.stdout.substring(0, 500)}, stderr=${apmResult.stderr.substring(0, 500)}`,
); );
console.log( logger.debug(
`[UpdateCenter] aptssInstalledResult: code=${aptssInstalledResult.code}, stdout=${aptssInstalledResult.stdout.substring(0, 500)}`, `[UpdateCenter] aptssInstalledResult: code=${aptssInstalledResult.code}, stdout=${aptssInstalledResult.stdout.substring(0, 500)}`,
); );
console.log( logger.debug(
`[UpdateCenter] apmInstalledResult: code=${apmInstalledResult.code}, stdout=${apmInstalledResult.stdout.substring(0, 500)}`, `[UpdateCenter] apmInstalledResult: code=${apmInstalledResult.code}, stdout=${apmInstalledResult.stdout.substring(0, 500)}`,
); );
@@ -452,11 +455,11 @@ export const loadUpdateCenterItems = async (
apmEnabled && apmResult.code === 0 apmEnabled && apmResult.code === 0
? parseApmUpgradableOutput(apmResult.stdout) ? parseApmUpgradableOutput(apmResult.stdout)
: []; : [];
console.log( logger.debug(
`[UpdateCenter] parsed aptssItems count=${aptssItems.length}`, `[UpdateCenter] parsed aptssItems count=${aptssItems.length}`,
aptssItems.map((i) => `${i.pkgname} ${i.currentVersion}->${i.nextVersion}`), aptssItems.map((i) => `${i.pkgname} ${i.currentVersion}->${i.nextVersion}`),
); );
console.log( logger.debug(
`[UpdateCenter] parsed apmItems count=${apmItems.length}`, `[UpdateCenter] parsed apmItems count=${apmItems.length}`,
apmItems.map((i) => `${i.pkgname} ${i.currentVersion}->${i.nextVersion}`), apmItems.map((i) => `${i.pkgname} ${i.currentVersion}->${i.nextVersion}`),
); );
@@ -467,7 +470,7 @@ export const loadUpdateCenterItems = async (
: "", : "",
apmInstalledResult.code === 0 ? apmInstalledResult.stdout : "", apmInstalledResult.code === 0 ? apmInstalledResult.stdout : "",
); );
console.log(`[UpdateCenter] installedSources size=${installedSources.size}`); logger.debug(`[UpdateCenter] installedSources size=${installedSources.size}`);
const [categorizedAptssItems, categorizedApmItems] = await Promise.all([ const [categorizedAptssItems, categorizedApmItems] = await Promise.all([
aptssAvailable ? enrichItemCategories(aptssItems) : Promise.resolve([]), aptssAvailable ? enrichItemCategories(aptssItems) : Promise.resolve([]),
@@ -481,11 +484,11 @@ export const loadUpdateCenterItems = async (
? enrichApmItems(categorizedApmItems, runCommand) ? enrichApmItems(categorizedApmItems, runCommand)
: Promise.resolve({ items: [], warnings: [] }), : Promise.resolve({ items: [], warnings: [] }),
]); ]);
console.log( logger.debug(
`[UpdateCenter] enrichedAptssItems: count=${enrichedAptssItems.items.length}, warnings=${enrichedAptssItems.warnings.length}`, `[UpdateCenter] enrichedAptssItems: count=${enrichedAptssItems.items.length}, warnings=${enrichedAptssItems.warnings.length}`,
enrichedAptssItems.warnings, enrichedAptssItems.warnings,
); );
console.log( logger.debug(
`[UpdateCenter] enrichedApmItems: count=${enrichedApmItems.items.length}, warnings=${enrichedApmItems.warnings.length}`, `[UpdateCenter] enrichedApmItems: count=${enrichedApmItems.items.length}, warnings=${enrichedApmItems.warnings.length}`,
enrichedApmItems.warnings, enrichedApmItems.warnings,
); );
@@ -495,7 +498,7 @@ export const loadUpdateCenterItems = async (
enrichItemIcons(enrichedApmItems.items), enrichItemIcons(enrichedApmItems.items),
installedSources, installedSources,
); );
console.log( logger.debug(
`[UpdateCenter] mergedItems count=${mergedItems.length}`, `[UpdateCenter] mergedItems count=${mergedItems.length}`,
mergedItems.map( mergedItems.map(
(i) => `${i.pkgname} (${i.source}) ${i.currentVersion}->${i.nextVersion}`, (i) => `${i.pkgname} (${i.source}) ${i.currentVersion}->${i.nextVersion}`,
@@ -606,7 +609,7 @@ const runCommandWithTimeout = (
export const runSystemUpdateSources = async ( export const runSystemUpdateSources = async (
storeFilter: StoreFilter = "both", storeFilter: StoreFilter = "both",
): Promise<{ aptss?: string; apm?: string }> => { ): Promise<{ aptss?: string; apm?: string }> => {
console.log( logger.debug(
`[UpdateCenter] runSystemUpdateSources called with storeFilter=${storeFilter}`, `[UpdateCenter] runSystemUpdateSources called with storeFilter=${storeFilter}`,
); );
@@ -621,7 +624,7 @@ export const runSystemUpdateSources = async (
const aptssAvailable = const aptssAvailable =
whichResult.code === 0 && whichResult.stdout.trim().length > 0; whichResult.code === 0 && whichResult.stdout.trim().length > 0;
if (aptssAvailable) { if (aptssAvailable) {
console.log("[UpdateCenter] Running: pkexec shell-caller aptss ssupdate"); logger.debug("[UpdateCenter] Running: pkexec shell-caller aptss ssupdate");
const superUserCmd = await findExecutable( const superUserCmd = await findExecutable(
SUPER_USER_COMMAND_CANDIDATES[0], SUPER_USER_COMMAND_CANDIDATES[0],
); );
@@ -635,7 +638,7 @@ export const runSystemUpdateSources = async (
result.code === 0 result.code === 0
? "ok" ? "ok"
: `failed: ${result.stderr.substring(0, 200)}`; : `failed: ${result.stderr.substring(0, 200)}`;
console.log("[UpdateCenter] aptss ssupdate result:", results.aptss); logger.debug("[UpdateCenter] aptss ssupdate result:", results.aptss);
} else { } else {
results.aptss = "failed: pkexec not found"; results.aptss = "failed: pkexec not found";
console.warn("[UpdateCenter] pkexec not found, skipping aptss update"); console.warn("[UpdateCenter] pkexec not found, skipping aptss update");
@@ -650,7 +653,7 @@ export const runSystemUpdateSources = async (
const apmAvailable = const apmAvailable =
whichResult.code === 0 && whichResult.stdout.trim().length > 0; whichResult.code === 0 && whichResult.stdout.trim().length > 0;
if (apmAvailable) { if (apmAvailable) {
console.log("[UpdateCenter] Running: pkexec shell-caller apm update"); logger.debug("[UpdateCenter] Running: pkexec shell-caller apm update");
const superUserCmd = await findExecutable( const superUserCmd = await findExecutable(
SUPER_USER_COMMAND_CANDIDATES[0], SUPER_USER_COMMAND_CANDIDATES[0],
); );
@@ -664,7 +667,7 @@ export const runSystemUpdateSources = async (
result.code === 0 result.code === 0
? "ok" ? "ok"
: `failed: ${result.stderr.substring(0, 200)}`; : `failed: ${result.stderr.substring(0, 200)}`;
console.log("[UpdateCenter] apm update result:", results.apm); logger.debug("[UpdateCenter] apm update result:", results.apm);
} else { } else {
results.apm = "failed: pkexec not found"; results.apm = "failed: pkexec not found";
console.warn("[UpdateCenter] pkexec not found, skipping apm update"); console.warn("[UpdateCenter] pkexec not found, skipping apm update");