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,