PRAGMA foreign_keys = ON; -- ========================================================= -- Vulnerability SQLite Database -- Schema Version: 3 -- ========================================================= -- ========================================================= -- 1. METADATA -- ========================================================= CREATE TABLE IF NOT EXISTS meta ( key TEXT PRIMARY KEY, value TEXT NOT NULL ); INSERT INTO meta (key, value) VALUES ('schema_version', '3') ON CONFLICT(key) DO NOTHING; -- ========================================================= -- 2. DATA SOURCES / LAST UPDATE / IMPORT STATUS -- ========================================================= CREATE TABLE IF NOT EXISTS sources ( name TEXT PRIMARY KEY, revision TEXT NOT NULL DEFAULT '', indexed INTEGER NOT NULL DEFAULT 0 CHECK (indexed IN (0, 1)), documents INTEGER NOT NULL DEFAULT 0 CHECK (documents >= 0), last_sync TEXT, last_import TEXT, import_status TEXT NOT NULL DEFAULT 'pending' CHECK ( import_status IN ( 'pending', 'success', 'unsupported', 'failed' ) ), import_errors INTEGER NOT NULL DEFAULT 0 CHECK (import_errors >= 0) ); CREATE INDEX IF NOT EXISTS idx_sources_status ON sources(import_status); -- ========================================================= -- 3. VULNERABILITIES -- ========================================================= CREATE TABLE IF NOT EXISTS vulnerabilities ( id TEXT PRIMARY KEY, published TEXT, modified TEXT, state TEXT, summary TEXT ); CREATE INDEX IF NOT EXISTS idx_vulnerabilities_modified ON vulnerabilities(modified); -- ========================================================= -- 4. ALIASES -- ========================================================= CREATE TABLE IF NOT EXISTS aliases ( alias TEXT NOT NULL, vulnerability_id TEXT NOT NULL REFERENCES vulnerabilities(id) ON DELETE CASCADE, PRIMARY KEY ( alias, vulnerability_id ) ); CREATE INDEX IF NOT EXISTS idx_aliases_vuln ON aliases(vulnerability_id); -- ========================================================= -- 5. AFFECTED PACKAGES (OSV) -- ========================================================= CREATE TABLE IF NOT EXISTS affected_packages ( id TEXT PRIMARY KEY, vulnerability_id TEXT NOT NULL REFERENCES vulnerabilities(id) ON DELETE CASCADE, ecosystem TEXT, package_name TEXT, ranges_json TEXT NOT NULL, versions_json TEXT NOT NULL, source TEXT NOT NULL ); CREATE INDEX IF NOT EXISTS idx_affected_vuln ON affected_packages(vulnerability_id); CREATE INDEX IF NOT EXISTS idx_affected_package ON affected_packages(ecosystem, package_name); -- ========================================================= -- 6. CPE CONDITION TREES (NVD) -- ========================================================= CREATE TABLE IF NOT EXISTS cpe_nodes ( id TEXT PRIMARY KEY, vulnerability_id TEXT NOT NULL REFERENCES vulnerabilities(id) ON DELETE CASCADE, parent_id TEXT REFERENCES cpe_nodes(id), operator TEXT NOT NULL CHECK (operator IN ('AND', 'OR')), negate INTEGER NOT NULL DEFAULT 0 CHECK (negate IN (0, 1)), source TEXT NOT NULL ); CREATE INDEX IF NOT EXISTS idx_cpe_nodes_vuln ON cpe_nodes(vulnerability_id); CREATE INDEX IF NOT EXISTS idx_cpe_nodes_parent ON cpe_nodes(parent_id); -- ========================================================= -- 7. CPE MATCHES (NVD) -- ========================================================= CREATE TABLE IF NOT EXISTS cpe_matches ( id TEXT PRIMARY KEY, vulnerability_id TEXT NOT NULL REFERENCES vulnerabilities(id) ON DELETE CASCADE, node_id TEXT REFERENCES cpe_nodes(id), criteria TEXT, vulnerable INTEGER CHECK (vulnerable IN (0, 1)), version_start_including TEXT, version_start_excluding TEXT, version_end_including TEXT, version_end_excluding TEXT, source TEXT NOT NULL ); CREATE INDEX IF NOT EXISTS idx_cpe_vuln ON cpe_matches(vulnerability_id); CREATE INDEX IF NOT EXISTS idx_cpe_matches_node ON cpe_matches(node_id); CREATE INDEX IF NOT EXISTS idx_cpe_matches_criteria ON cpe_matches(criteria); -- IMPORTANT: -- AND / OR / negate conditions must be evaluated as a tree. -- They must not be converted into independent vulnerability -- assertions, because that can produce false positives. -- ========================================================= -- 8. RED HAT CSAF ADVISORIES -- ========================================================= CREATE TABLE IF NOT EXISTS redhat_advisories ( id TEXT PRIMARY KEY, title TEXT, initial_release_date TEXT, current_release_date TEXT, product_tree_json TEXT NOT NULL ); -- ========================================================= -- 9. RED HAT CSAF CVE RELATIONSHIPS -- ========================================================= CREATE TABLE IF NOT EXISTS redhat_advisory_cves ( id TEXT PRIMARY KEY, advisory_id TEXT NOT NULL REFERENCES redhat_advisories(id) ON DELETE CASCADE, cve_id TEXT NOT NULL REFERENCES vulnerabilities(id) ON DELETE CASCADE, product_status_json TEXT NOT NULL, remediations_json TEXT NOT NULL, UNIQUE ( advisory_id, cve_id ) ); CREATE INDEX IF NOT EXISTS idx_redhat_advisory_cves_cve ON redhat_advisory_cves(cve_id); CREATE INDEX IF NOT EXISTS idx_redhat_advisory_cves_advisory ON redhat_advisory_cves(advisory_id); -- ========================================================= -- END OF SCHEMA VERSION 3 -- =========================================================