Files
ld-sysinfo-server-backend/scripts/analyzeDatabaseQuality.js
Bailey Taylor 2b5aaa1401
All checks were successful
Build & Deploy Backend / build (push) Successful in 47s
Build & Deploy Backend / deploy (push) Successful in 31s
Updated fetchcve scripts with enrichments.
2025-10-08 11:07:04 +08:00

170 lines
6.0 KiB
JavaScript

#!/usr/bin/env node
import mysql from 'mysql2/promise';
function log(msg) {
const now = new Date().toLocaleString('en-AU', {
day: '2-digit', month: 'short', year: 'numeric',
hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: true
}).replace(/\b(AM|PM)\b/, m => m.toLowerCase());
console.log(`[${now}] ${msg}`);
}
async function analyzeDatabaseQuality() {
const db = await mysql.createConnection({
host: process.env.DB_HOST,
port: process.env.DB_PORT || 3306,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
});
log('🔍 Analyzing CVE Database Quality...\n');
log('━'.repeat(70));
// Total CVEs
const [total] = await db.query('SELECT COUNT(*) as count FROM cves');
log(`📊 Total CVEs: ${total[0].count.toLocaleString()}`);
// CVEs with CVSS v3 scores
const [v3] = await db.query('SELECT COUNT(*) as count FROM cves WHERE cvss_score_v3 IS NOT NULL');
const v3Pct = ((v3[0].count / total[0].count) * 100).toFixed(1);
log(`📈 CVEs with CVSS v3 scores: ${v3[0].count.toLocaleString()} (${v3Pct}%)`);
// CVEs with CVSS v2 scores
const [v2] = await db.query('SELECT COUNT(*) as count FROM cves WHERE cvss_score_v2 IS NOT NULL');
const v2Pct = ((v2[0].count / total[0].count) * 100).toFixed(1);
log(`📈 CVEs with CVSS v2 scores: ${v2[0].count.toLocaleString()} (${v2Pct}%)`);
// CVEs with CVSS v4 scores
const [v4] = await db.query('SELECT COUNT(*) as count FROM cves WHERE cvss_score_v4 IS NOT NULL');
const v4Pct = ((v4[0].count / total[0].count) * 100).toFixed(1);
log(`📈 CVEs with CVSS v4 scores: ${v4[0].count.toLocaleString()} (${v4Pct}%)`);
// CVEs with CWE IDs
const [cwe] = await db.query('SELECT COUNT(*) as count FROM cves WHERE cwe_ids IS NOT NULL AND cwe_ids != ""');
const cwePct = ((cwe[0].count / total[0].count) * 100).toFixed(1);
log(`🏷️ CVEs with CWE IDs: ${cwe[0].count.toLocaleString()} (${cwePct}%)`);
// CVEs with references
const [refs] = await db.query('SELECT COUNT(*) as count FROM cves WHERE `references` IS NOT NULL AND `references` != ""');
const refsPct = ((refs[0].count / total[0].count) * 100).toFixed(1);
log(`🔗 CVEs with references: ${refs[0].count.toLocaleString()} (${refsPct}%)`);
// KEV data
const [kev] = await db.query('SELECT COUNT(*) as count FROM kev_catalog');
log(`🛡️ Known Exploited Vulnerabilities (KEV): ${kev[0].count.toLocaleString()}`);
// Microsoft CVEs
const [msrc] = await db.query('SELECT COUNT(*) as count FROM microsoft_cves');
log(`🖥️ Microsoft CVEs: ${msrc[0].count.toLocaleString()}`);
// CPE matches
const [cpe] = await db.query('SELECT COUNT(*) as count FROM cpe_matches');
log(`💿 CPE matches (affected software): ${cpe[0].count.toLocaleString()}`);
log('\n━'.repeat(70));
log('📅 CVEs by Severity (CVSS v3):');
log('━'.repeat(70));
const [severity] = await db.query(`
SELECT
severity_v3,
COUNT(*) as count,
ROUND(AVG(cvss_score_v3), 1) as avg_score
FROM cves
WHERE severity_v3 IS NOT NULL
GROUP BY severity_v3
ORDER BY
CASE severity_v3
WHEN 'CRITICAL' THEN 1
WHEN 'HIGH' THEN 2
WHEN 'MEDIUM' THEN 3
WHEN 'LOW' THEN 4
ELSE 5
END
`);
severity.forEach(row => {
const pct = ((row.count / total[0].count) * 100).toFixed(1);
const icon = {
'CRITICAL': '🔴',
'HIGH': '🟠',
'MEDIUM': '🟡',
'LOW': '🟢'
}[row.severity_v3] || '⚪';
log(`${icon} ${(row.severity_v3 || 'UNKNOWN').padEnd(10)} ${row.count.toString().padStart(8)} (${pct.padStart(5)}%) - Avg: ${row.avg_score}`);
});
log('\n━'.repeat(70));
log('📅 Recent Activity (Last 30 Days):');
log('━'.repeat(70));
const [recent] = await db.query(`
SELECT COUNT(*) as count
FROM cves
WHERE last_modified_date >= DATE_SUB(NOW(), INTERVAL 30 DAY)
`);
log(`🆕 CVEs modified in last 30 days: ${recent[0].count.toLocaleString()}`);
const [recentPub] = await db.query(`
SELECT COUNT(*) as count
FROM cves
WHERE published_date >= DATE_SUB(NOW(), INTERVAL 30 DAY)
`);
log(`📝 CVEs published in last 30 days: ${recentPub[0].count.toLocaleString()}`);
log('\n━'.repeat(70));
log('🎯 Data Quality Score:');
log('━'.repeat(70));
const qualityScore = (
(parseFloat(v3Pct) * 0.3) + // 30% weight on CVSS v3
(parseFloat(cwePct) * 0.2) + // 20% weight on CWE
(parseFloat(refsPct) * 0.2) + // 20% weight on references
((cpe[0].count > 0 ? 100 : 0) * 0.15) + // 15% weight on CPE existence
((kev[0].count > 0 ? 100 : 0) * 0.15) // 15% weight on KEV data
);
log(`Overall Quality: ${qualityScore.toFixed(1)}%`);
if (qualityScore >= 90) log('✅ Excellent - Highly enriched database');
else if (qualityScore >= 75) log('✅ Good - Well enriched database');
else if (qualityScore >= 60) log('⚠️ Fair - Some enrichment needed');
else log('❌ Poor - Significant enrichment needed');
log('\n━'.repeat(70));
log('💡 Recommendations:');
log('━'.repeat(70));
if (parseFloat(v3Pct) < 80) {
log('⚠️ Run CVE enrichment to get more CVSS v3 scores');
log(' Use: POST /api/admin/scripts/fetch-cve (runs fetchCVE_v2.js in enrichment mode)');
}
if (parseFloat(cwePct) < 70) {
log('⚠️ Low CWE coverage - consider running enrichment');
}
if (kev[0].count < 1000) {
log('⚠️ KEV data seems low - run: POST /api/admin/scripts/fetch-kev');
}
if (msrc[0].count < 10000) {
log('⚠️ Microsoft CVE data seems low - run: POST /api/admin/scripts/fetch-msrc');
}
if (recent[0].count < 100) {
log('⚠️ No recent updates detected - run daily sync to stay current');
log(' Use: POST /api/admin/scripts/fetch-cve');
}
await db.end();
log('\n✅ Analysis complete!\n');
}
analyzeDatabaseQuality().catch(err => {
console.error('❌ Error:', err.message);
process.exit(1);
});