From 6625071a101cef7105166f372e08280af5507a69 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 24 Mar 2026 14:34:06 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20address=20code=20review=20feedback=20?= =?UTF-8?q?=E2=80=94=20input=20validation=20+=20date=20parsing=20safety?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - daily-scan.js: validate date in manifest.last_scan, fix data.used=0 falsy check - quota-audit.js: explicit null check for data.used - guard-health.js: validate date in health_check.last_check - weekly-full.js: path traversal guard for scriptPath Co-authored-by: qinfendebingshuo <207279273+qinfendebingshuo@users.noreply.github.com> Agent-Logs-Url: https://github.com/qinfendebingshuo/guanghulab/sessions/ed7579c8-d43e-4a14-bd91-b3ef6bc314ec --- skyeye/scripts/daily-scan.js | 10 +++++++--- skyeye/scripts/guard-health.js | 11 ++++++++--- skyeye/scripts/quota-audit.js | 2 +- skyeye/scripts/weekly-full.js | 11 ++++++++++- 4 files changed, 26 insertions(+), 8 deletions(-) diff --git a/skyeye/scripts/daily-scan.js b/skyeye/scripts/daily-scan.js index 7f46bb64..1dfadd73 100644 --- a/skyeye/scripts/daily-scan.js +++ b/skyeye/scripts/daily-scan.js @@ -48,9 +48,13 @@ function sense() { // Check last scan freshness (48h threshold) if (manifest.last_scan) { - const lastScanAge = Date.now() - new Date(manifest.last_scan).getTime(); + const lastScanTime = new Date(manifest.last_scan).getTime(); + if (isNaN(lastScanTime)) { + result.issues.push('infra-manifest.last_scan 日期格式无效'); + } + const lastScanAge = isNaN(lastScanTime) ? 0 : Date.now() - lastScanTime; const hours = Math.round(lastScanAge / (1000 * 60 * 60)); - if (hours > 48) { + if (!isNaN(lastScanTime) && hours > 48) { result.issues.push(`infra-manifest 最后扫描距今 ${hours}h,超过 48h 阈值`); } } @@ -125,7 +129,7 @@ function auditQuotas() { if (ledger.services) { for (const [name, data] of Object.entries(ledger.services)) { let usagePct = 0; - if (data.limit && data.used) { + if (data.limit && data.used !== undefined && data.used !== null) { usagePct = Math.round((data.used / data.limit) * 100 * 10) / 10; } diff --git a/skyeye/scripts/guard-health.js b/skyeye/scripts/guard-health.js index 52160534..9a89bbc1 100644 --- a/skyeye/scripts/guard-health.js +++ b/skyeye/scripts/guard-health.js @@ -69,9 +69,14 @@ function checkGuardHealth(filePath) { // Check 5: Last heartbeat freshness (if available) if (guard.health_check?.last_check) { - const lastCheckAge = Date.now() - new Date(guard.health_check.last_check).getTime(); - const intervalMs = (guard.health_check.interval_hours || 6) * 60 * 60 * 1000; - result.checks.heartbeat_fresh = lastCheckAge < intervalMs * 3; // 3x tolerance + const lastCheckTime = new Date(guard.health_check.last_check).getTime(); + if (!isNaN(lastCheckTime)) { + const lastCheckAge = Date.now() - lastCheckTime; + const intervalMs = (guard.health_check.interval_hours || 6) * 60 * 60 * 1000; + result.checks.heartbeat_fresh = lastCheckAge < intervalMs * 3; // 3x tolerance + } else { + result.checks.heartbeat_fresh = null; // Invalid date + } } else { result.checks.heartbeat_fresh = null; // No heartbeat recorded yet } diff --git a/skyeye/scripts/quota-audit.js b/skyeye/scripts/quota-audit.js index 27b56764..bb496b73 100644 --- a/skyeye/scripts/quota-audit.js +++ b/skyeye/scripts/quota-audit.js @@ -48,7 +48,7 @@ function auditService(name, data) { actions: [] }; - if (data.limit && data.used !== undefined) { + if (data.limit && data.used !== undefined && data.used !== null) { result.usage_percent = data.limit > 0 ? Math.round((data.used / data.limit) * 100 * 10) / 10 : 0; diff --git a/skyeye/scripts/weekly-full.js b/skyeye/scripts/weekly-full.js index d405bcf6..e0649ede 100644 --- a/skyeye/scripts/weekly-full.js +++ b/skyeye/scripts/weekly-full.js @@ -47,8 +47,17 @@ function runPhase(name, scriptPath) { return result; } + // Validate scriptPath is within expected directory + const resolvedScript = path.resolve(scriptPath); + const resolvedScriptsDir = path.resolve(SCRIPTS_DIR); + if (!resolvedScript.startsWith(resolvedScriptsDir)) { + result.status = 'error'; + result.error = `Script path outside expected directory: ${scriptPath}`; + return result; + } + try { - result.output = execSync(`node "${scriptPath}"`, { + result.output = execSync(`node "${resolvedScript}"`, { cwd: path.resolve(SKYEYE_DIR, '..'), encoding: 'utf8', timeout: 60000,