Files
ld-sysinfo-server-backend/scripts/verifyCVECount.js
Bailey Taylor c43b3a65c5
All checks were successful
Build & Deploy Backend / build (push) Successful in 47s
Build & Deploy Backend / deploy (push) Successful in 31s
New Github support for CVE verification.
2025-10-08 10:41:19 +08:00

199 lines
5.6 KiB
JavaScript
Executable File
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env node
import fs from 'fs';
import { execSync } from 'child_process';
import mysql from 'mysql2/promise';
import path from 'path';
const REPO_URL = 'https://github.com/CVEProject/cvelistV5.git';
const REPO_DIR = './cvelistV5';
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());
const line = `[${now}] ${msg}`;
console.log(line);
}
async function cloneOrPullRepo() {
log('📦 Checking CVE repository...');
if (fs.existsSync(REPO_DIR)) {
log('🔄 Repository exists, pulling latest changes...');
try {
execSync('git pull', { cwd: REPO_DIR, stdio: 'inherit' });
log('✅ Repository updated');
} catch (err) {
log(`⚠️ Git pull failed, trying fresh clone: ${err.message}`);
execSync(`rm -rf ${REPO_DIR}`);
execSync(`git clone --depth 1 ${REPO_URL} ${REPO_DIR}`, { stdio: 'inherit' });
}
} else {
log('📥 Cloning CVE repository (this may take a while)...');
execSync(`git clone --depth 1 ${REPO_URL} ${REPO_DIR}`, { stdio: 'inherit' });
log('✅ Repository cloned');
}
}
function countCVEsInRepo() {
log('🔍 Counting CVEs in repository...');
const cvesDir = path.join(REPO_DIR, 'cves');
let totalCount = 0;
const yearCounts = {};
if (!fs.existsSync(cvesDir)) {
log('❌ CVEs directory not found');
return { total: 0, byYear: {} };
}
// Iterate through year directories (e.g., cves/2023/)
const years = fs.readdirSync(cvesDir).filter(f => /^\d{4}$/.test(f));
for (const year of years) {
const yearPath = path.join(cvesDir, year);
if (!fs.statSync(yearPath).isDirectory()) continue;
let yearCount = 0;
// Each year has subdirectories like 0xxx, 1xxx, etc.
const subdirs = fs.readdirSync(yearPath);
for (const subdir of subdirs) {
const subdirPath = path.join(yearPath, subdir);
if (!fs.statSync(subdirPath).isDirectory()) continue;
// Count .json files in this subdirectory
const files = fs.readdirSync(subdirPath).filter(f => f.endsWith('.json'));
yearCount += files.length;
}
totalCount += yearCount;
yearCounts[year] = yearCount;
}
log(`📊 Found ${totalCount} CVE JSON files in repository`);
return { total: totalCount, byYear: yearCounts };
}
async function countCVEsInDatabase() {
log('🗄️ Counting CVEs in database...');
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,
});
// Total count
const [totalRows] = await db.query('SELECT COUNT(*) as total FROM cves');
const total = totalRows[0].total;
// Count by year
const [yearRows] = await db.query(`
SELECT
YEAR(published_date) as year,
COUNT(*) as count
FROM cves
WHERE published_date IS NOT NULL
GROUP BY YEAR(published_date)
ORDER BY year
`);
const byYear = {};
yearRows.forEach(row => {
byYear[row.year] = row.count;
});
await db.end();
log(`📊 Found ${total} CVEs in database`);
return { total, byYear };
}
function compareResults(repo, db) {
log('\n📋 Comparison Report:');
log('━'.repeat(60));
log(`Repository Total: ${repo.total.toLocaleString()}`);
log(`Database Total: ${db.total.toLocaleString()}`);
log(`Difference: ${(db.total - repo.total).toLocaleString()}`);
log('━'.repeat(60));
// Get all years from both sources
const allYears = new Set([
...Object.keys(repo.byYear),
...Object.keys(db.byYear)
]);
const sortedYears = Array.from(allYears).sort();
log('\n📅 Year-by-Year Breakdown:');
log('━'.repeat(60));
log('Year | Repository | Database | Difference');
log('━'.repeat(60));
const missingYears = [];
for (const year of sortedYears) {
const repoCount = repo.byYear[year] || 0;
const dbCount = db.byYear[year] || 0;
const diff = dbCount - repoCount;
const diffStr = diff >= 0 ? `+${diff}` : diff.toString();
log(`${year} | ${repoCount.toString().padStart(10)} | ${dbCount.toString().padStart(9)} | ${diffStr}`);
if (Math.abs(diff) > 100) {
missingYears.push({ year, repoCount, dbCount, diff });
}
}
log('━'.repeat(60));
if (missingYears.length > 0) {
log('\n⚠ Years with significant differences (>100):');
missingYears.forEach(({ year, repoCount, dbCount, diff }) => {
log(` ${year}: ${diff > 0 ? 'Extra' : 'Missing'} ${Math.abs(diff)} CVEs`);
});
}
const percentComplete = ((db.total / repo.total) * 100).toFixed(2);
log(`\n✅ Database is ${percentComplete}% complete`);
if (db.total >= repo.total) {
log('🎉 Your database has all CVEs from the official repository!');
} else {
log(`⚠️ Missing ${(repo.total - db.total).toLocaleString()} CVEs`);
}
}
async function main() {
try {
log('🚀 Starting CVE verification...\n');
// Step 1: Clone or pull repo
await cloneOrPullRepo();
// Step 2: Count CVEs in repo
const repoStats = countCVEsInRepo();
// Step 3: Count CVEs in database
const dbStats = await countCVEsInDatabase();
// Step 4: Compare
compareResults(repoStats, dbStats);
log('\n✅ Verification complete!');
} catch (err) {
log(`❌ Error: ${err.message}`);
console.error(err);
process.exit(1);
}
}
main();