Fix: Enable multi-vendor support for CVE entries

- Changed CVEs table constraint from UNIQUE(cve_id) to UNIQUE(cve_id, vendor)
- Added vendor column to documents table for proper file organization
- Updated backend INSERT statements to include vendor field in both CVE and document creation
- Fixed document retrieval to filter by vendor
- Created corrected setup.js that includes multi-vendor support from initial setup
- Added migration scripts for existing databases

Resolves #1: Users can now add the same CVE-ID with multiple different vendors, each maintaining separate document storage organized as CVE-ID/Vendor/files
This commit is contained in:
2026-01-28 14:49:03 +00:00
parent b9421ea0e9
commit 88c33cae04
3 changed files with 154 additions and 86 deletions

View File

@@ -1,5 +1,5 @@
// Setup Script for CVE Database
// This creates a fresh database ready for new CVE entries
// This creates a fresh database with multi-vendor support built-in
const sqlite3 = require('sqlite3').verbose();
const fs = require('fs');
@@ -18,19 +18,21 @@ function initializeDatabase() {
const schema = `
CREATE TABLE IF NOT EXISTS cves (
id INTEGER PRIMARY KEY AUTOINCREMENT,
cve_id VARCHAR(20) UNIQUE NOT NULL,
cve_id VARCHAR(20) NOT NULL,
vendor VARCHAR(100) NOT NULL,
severity VARCHAR(20) NOT NULL,
description TEXT,
published_date DATE,
status VARCHAR(50) DEFAULT 'Open',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE(cve_id, vendor)
);
CREATE TABLE IF NOT EXISTS documents (
id INTEGER PRIMARY KEY AUTOINCREMENT,
cve_id VARCHAR(20) NOT NULL,
vendor VARCHAR(100) NOT NULL,
name VARCHAR(255) NOT NULL,
type VARCHAR(50) NOT NULL,
file_path VARCHAR(500) NOT NULL,
@@ -54,6 +56,7 @@ function initializeDatabase() {
CREATE INDEX IF NOT EXISTS idx_severity ON cves(severity);
CREATE INDEX IF NOT EXISTS idx_status ON cves(status);
CREATE INDEX IF NOT EXISTS idx_doc_cve_id ON documents(cve_id);
CREATE INDEX IF NOT EXISTS idx_doc_vendor ON documents(vendor);
CREATE INDEX IF NOT EXISTS idx_doc_type ON documents(type);
INSERT OR IGNORE INTO required_documents (vendor, document_type, is_mandatory, description) VALUES
@@ -66,6 +69,7 @@ function initializeDatabase() {
CREATE VIEW IF NOT EXISTS cve_document_status AS
SELECT
c.id as record_id,
c.cve_id,
c.vendor,
c.severity,
@@ -80,8 +84,8 @@ function initializeDatabase() {
ELSE 'Missing Required Docs'
END as compliance_status
FROM cves c
LEFT JOIN documents d ON c.cve_id = d.cve_id
GROUP BY c.cve_id, c.vendor, c.severity, c.status;
LEFT JOIN documents d ON c.cve_id = d.cve_id AND c.vendor = d.vendor
GROUP BY c.id, c.cve_id, c.vendor, c.severity, c.status;
`;
db.exec(schema, (err) => {
@@ -107,17 +111,21 @@ function createUploadsDirectory() {
// Add sample CVE data (optional - for testing)
async function addSampleData(db) {
console.log('\n📝 Would you like to add sample CVE data for testing? (y/n)');
console.log('\n📝 Adding sample CVE data for testing...');
// For automated setup, we'll skip this. Uncomment the code below if you want samples.
/*
const sampleCVEs = [
{
cve_id: 'CVE-2024-SAMPLE-1',
vendor: 'Microsoft',
severity: 'Critical',
description: 'Sample vulnerability for testing',
description: 'Sample remote code execution vulnerability',
published_date: '2024-01-15'
},
{
cve_id: 'CVE-2024-SAMPLE-1',
vendor: 'Cisco',
severity: 'High',
description: 'Sample remote code execution vulnerability',
published_date: '2024-01-15'
}
];
@@ -131,16 +139,37 @@ async function addSampleData(db) {
(err) => {
if (err) reject(err);
else {
console.log(` ✓ Added sample CVE: ${cve.cve_id}`);
console.log(` ✓ Added sample: ${cve.cve_id} / ${cve.vendor}`);
resolve();
}
}
);
});
}
*/
console.log(' Skipping sample data - you can add CVEs through the API or dashboard');
console.log(' Sample data added - demonstrates multi-vendor support');
}
// Verify database structure
async function verifySetup(db) {
return new Promise((resolve) => {
db.get('SELECT sql FROM sqlite_master WHERE type="table" AND name="cves"', (err, row) => {
if (err) {
console.error('Warning: Could not verify setup:', err);
} else {
console.log('\n📋 CVEs table structure:');
console.log(row.sql);
// Check if UNIQUE constraint is correct
if (row.sql.includes('UNIQUE(cve_id, vendor)')) {
console.log('\n✅ Multi-vendor support: ENABLED');
} else {
console.log('\n⚠ Warning: Multi-vendor constraint may not be set correctly');
}
}
resolve();
});
});
}
// Display setup summary
@@ -151,33 +180,37 @@ function displaySummary() {
console.log('\n📊 What was created:');
console.log(' ✓ SQLite database (cve_database.db)');
console.log(' ✓ Tables: cves, documents, required_documents');
console.log(' ✓ Multi-vendor support with UNIQUE(cve_id, vendor)');
console.log(' ✓ Vendor column in documents table');
console.log(' ✓ Indexes for fast queries');
console.log(' ✓ Document compliance view');
console.log(' ✓ Uploads directory for file storage');
console.log('\n📁 File structure will be:');
console.log(' uploads/');
console.log(' └── CVE-XXXX-XXXX/');
console.log(' ── VendorName/');
console.log(' ├── advisory.pdf');
console.log(' ── email.pdf');
console.log(' └── screenshot.png');
console.log(' ── Vendor1/');
console.log(' ├── advisory.pdf');
console.log(' ── screenshot.png');
console.log(' └── Vendor2/');
console.log(' └── advisory.pdf');
console.log('\n🚀 Next steps:');
console.log(' 1. Start the backend API:');
console.log(' → cd backend && node server.js');
console.log(' 2. Start the frontend:');
console.log(' → cd frontend && npm start');
console.log(' 3. Open http://localhost:3000');
console.log(' 4. Start adding CVEs and uploading documents!');
console.log('\n💡 Tips:');
console.log(' • Use the Quick Check to verify CVE status');
console.log(' • Upload documents through the dashboard');
console.log(' • Documents are auto-organized by CVE ID → Vendor');
console.log(' 4. Start adding CVEs with multiple vendors!');
console.log('\n💡 Key Features:');
console.log(' • Add same CVE-ID with different vendors');
console.log(' • Each vendor has separate document storage');
console.log(' • Quick Check shows all vendors for a CVE');
console.log(' • Document compliance tracking per vendor');
console.log(' • Required docs: Advisory (mandatory for most vendors)\n');
}
// Main execution
async function main() {
console.log('🚀 CVE Database Setup\n');
console.log('🚀 CVE Database Setup (Multi-Vendor Support)\n');
console.log('════════════════════════════════════════\n');
try {
@@ -187,13 +220,16 @@ async function main() {
// Initialize database
const db = await initializeDatabase();
// Optionally add sample data
// Add sample data
await addSampleData(db);
// Verify setup
await verifySetup(db);
// Close database connection
db.close((err) => {
if (err) console.error('Error closing database:', err);
else console.log('✓ Database connection closed');
else console.log('\n✓ Database connection closed');
// Display summary
displaySummary();
@@ -206,4 +242,4 @@ async function main() {
}
// Run the setup
main();
main();