Lompat ke konten
dokumentasi.id
Commit e4397d1
v1
Star2,4 rb

Kamu membaca versi lama. Halaman ini hanya bisa dibaca.

2.6

CVE Intelligence dan RAG

Modul modules/cve_intelligence/ menghasilkan dua artefak terpisah: basis data SQLite data/cve_intelligence.db dan index RAG berupa pickle data/cve_rag_index.pkl. CVEMatcher membaca basis data itu untuk mengayakan temuan dengan related_cves, cve_references, dan cve_links. CVERagIndex membangun ruang vektor TF-IDF di atas korpus CVE dan memakainya untuk mencari CVE yang mirip dengan sebuah temuan. Keduanya hanya aktif ketika konfigurasi menyalakannya, dan keduanya membaca artefak yang sama sekali tidak dibuat saat scan berjalan.

Artefak dan titik pemakaian

graph TD
  UPD["scripts/update_cve_database.py"] --> SCR["CVEScraper.scrape_latest_vulnerabilities"]
  SCR --> DB[("data/cve_intelligence.db")]
  BLD["scripts/build_cve_rag_index.py"] --> BUILD["CVERagIndex.build"]
  DB --> BUILD
  BUILD --> SAVE["CVERagIndex.save"]
  SAVE --> PKL[("data/cve_rag_index.pkl")]
  FACT["get_cve_matcher"] --> MATCH["CVEMatcher"]
  DB --> MATCH
  MATCH --> ENR["enrich_vulnerability"]
  ENR --> VULN["temuan: related_cves, cve_references, cve_links"]
  PKL --> LOAD["CVERagIndex.load"]
  LOAD --> SEARCH["rag.search"]
  SEARCH --> RAGV["temuan: cve_references, rag_matched"]
  style DB fill:#336791,color:#fff
  style PKL fill:#8b5cf6,color:#fff
  style ENR fill:#2d7d46,color:#fff
  style SEARCH fill:#2d7d46,color:#fff
  style FACT fill:#f59e0b,color:#000
  style BUILD fill:#f59e0b,color:#000
%% fig: Dari skrip pembangun ke pemakaian saat scan
%% desc: Skrip pembaruan mengisi SQLite, skrip index membaca SQLite lalu menulis pickle, dan saat scan kedua artefak hanya dibaca oleh CVEMatcher dan CVERagIndex.
Fig. 1: Dari skrip pembangun ke pemakaian saat scanSkrip pembaruan mengisi SQLite, skrip index membaca SQLite lalu menulis pickle, dan saat scan kedua artefak hanya dibaca oleh CVEMatcher dan CVERagIndex.
ArtefakDibangun olehDibaca olehKunci konfigurasi
data/cve_intelligence.dbscripts/update_cve_database.py lewat CVEScraperCVEMatcher, CVERagIndex._load_cve_rowsexperimental.cve_database_path, cve_intelligence.database_path
data/cve_rag_index.pklCVERagIndex.build lalu CVERagIndex.saveCVERagIndex.loadrag.index_path

Skrip pembangun tidak berbagi state dengan proses scan. scripts/build_cve_rag_index.py memuat konfigurasi lewat ConfigLoader.load, memanggil rag.build(args.cve_db, interactive=True), lalu rag.save() dan mencetak [+] Index saved to ... bersama jumlah CVE yang terindeks (scripts/build_cve_rag_index.py:19-48).

Pembaruan basis data CVE

scripts/update_cve_database.py menyiapkan CVEScraper("data/cve_intelligence.db", use_browser=True) lalu menampilkan statistik awal total_cves, total_exploits, dan total_technologies sebelum menjalankan empat langkah (scripts/update_cve_database.py:84-99).

LangkahFungsiSumberBatas
1/4scrape_latest_vulnerabilitiesNVD RSS, CISA KEVmax_items=100
2/4scrape_multi_sourceNVD Web, MITRE, Vulners, GitHublatest_cves[:50]
3/4tidak ada, NVD API dinonaktifkan—nvd_count = 0
4/4scraper.scrape_exploit_dbExploit-DB via Playwrightlimit=500

Langkah 2/4 hanya berjalan bila langkah 1/4 mengembalikan daftar CVE, dan hasil tiap langkah disimpan di scraping_results untuk tabel ringkasan di akhir (scripts/update_cve_database.py:105-137).

⚠️ Setiap langkah menangkap exception-nya sendiri dan mengembalikan 0, misalnya console.print(f"[red]✗[/red] Error fetching latest vulnerabilities: {e}\n") lalu return 0, [] (scripts/update_cve_database.py:32-55). Kegagalan jaringan karena itu tidak menghentikan skrip dan tidak menghasilkan exit code gagal; periksa tabel ringkasan untuk memastikan ada baris yang benar-benar masuk.

Isi basis data tidak harus lengkap untuk membuat CVEMatcher berguna. ensure_seed_if_empty(min_rows=5) membuat tabel cve_entries, cve_exploits, dan cve_technologies lalu menyisipkan seed bila jumlah baris di bawah batas (modules/cve_intelligence/cve_matcher.py:61-64). Seed itu berisi 16 CVE sinyal tinggi seperti CVE-2021-44228 (Log4Shell) dan CVE-2014-6271 (Shellshock) (modules/cve_intelligence/cve_matcher.py:112-130), dan id semu CVE-2017-5638-SQL diganti menjadi CVE-2012-2122 sebelum disisipkan (modules/cve_intelligence/cve_matcher.py:296-303).

Pembangunan index RAG

CVERagIndex.__init__ membaca rag.index_path (default data/cve_rag_index.pkl), rag.top_k (default 5), rag.min_score (default 0.15), dan rag.auto_rebuild (default True) dari blok rag pada konfigurasi (modules/cve_intelligence/rag_index.py:48-59).

KunciDefault di kodeDipakai oleh
rag.index_pathdata/cve_rag_index.pklload, save, is_stale
rag.top_k5 (engine memakai default 3)search
rag.min_score0.15search
rag.auto_rebuildTrueis_stale di engine
rag.enabledFalsegerbang pengayaan RAG di engine

build mengambil baris lewat _load_cve_rows, yang menjalankan SELECT c.cve_id, c.description, c.cvss_score, c.severity, GROUP_CONCAT(t.technology, '|') dengan LEFT JOIN cve_technologies dan GROUP BY c.cve_id; bila tabel cve_entries tidak ada, fungsi mencatat RAG: cve_entries table missing dan mengembalikan daftar kosong (modules/cve_intelligence/rag_index.py:172-199). Setiap dokumen adalah gabungan description dan teknologi yang di-join spasi, lalu build mengembalikan False saat DB tidak ditemukan, tabel kosong, atau tidak ada dokumen tersisa (modules/cve_intelligence/rag_index.py:117-132).

Vektorisasi memakai TfidfVectorizer(stop_words="english", ngram_range=(1, 2), max_features=50000, sublinear_tf=True), dan build mencatat hasilnya sebagai RAG index built: {len(meta)} CVEs, vocab={len(vectorizer.vocabulary_)} (modules/cve_intelligence/rag_index.py:157-170). save menolak index yang belum dibangun dengan RuntimeError("Cannot save unbuilt index"), lalu menulis payload berisi vectorizer, matrix, cve_meta, built_at, dan doc_count (modules/cve_intelligence/rag_index.py:100-115).

load mengembalikan False bila berkas pickle tidak ada atau scikit-learn tidak tersedia, dan mencatat RAG: scikit-learn not available; cannot load index (modules/cve_intelligence/rag_index.py:76-82). Pemeriksaan dependensi itu ada di _ensure_sklearn: tanpa TTY, fungsi langsung mengembalikan False tanpa memasang apa pun; dengan TTY, fungsi menanyakan [!] RAG needs scikit-learn. Install now? [y/N]: lalu menjalankan pip install scikit-learn (modules/cve_intelligence/rag_index.py:18-45).

search mengembalikan [] bila index belum dimuat atau query kosong, menghitung cosine_similarity terhadap matriks TF-IDF, mengambil k skor tertinggi dengan np.argsort(-scores), membuang hit di bawah min_score, dan menambahkan field score pada setiap hasil (modules/cve_intelligence/rag_index.py:201-223). is_stale menyatakan index usang bila pickle tidak ada, atau bila st_mtime pickle lebih tua daripada basis data CVE (modules/cve_intelligence/rag_index.py:68-74).

⚠️ Bila direktori data/ dihapus tetapi rag.enabled tetap true, build dan load sama-sama gagal tanpa exception yang keluar: build mencetak RAG: CVE DB not found at data/cve_intelligence.db dan pengayaan dilewati tanpa pesan tambahan (modules/cve_intelligence/rag_index.py:123-125). Pada mode non-interaktif, instalasi scikit-learn tidak akan dipicu sama sekali (modules/cve_intelligence/rag_index.py:26-28).

Pencocokan temuan dengan CVEMatcher

graph LR
  V["dict temuan"] --> T["_search_terms_for_type"]
  T --> Q{"search_terms kosong?"}
  Q -- tidak --> SQL["cve_entries WHERE description LIKE ... LIMIT 5"]
  Q -- ya --> BLOB["gabung type + description"]
  BLOB --> T2["_search_terms_for_type(blob)"]
  T2 --> SQL
  SQL --> REL["related_cves + cve_references + cve_matched"]
  REL --> LIVE["_live_enrich"]
  LIVE --> LINKS["_attach_links_only"]
  style SQL fill:#336791,color:#fff
  style REL fill:#2d7d46,color:#fff
  style BLOB fill:#f59e0b,color:#000
  style LINKS fill:#8b5cf6,color:#fff
%% fig: Jalur enrich_vulnerability dari tipe temuan ke CVE terkait
%% desc: Tipe temuan diterjemahkan menjadi pola LIKE, dicocokkan ke cve_entries dengan batas lima baris, lalu dilengkapi lookup live dan tautan referensi.
Fig. 2: Jalur enrich_vulnerability dari tipe temuan ke CVE terkaitTipe temuan diterjemahkan menjadi pola LIKE, dicocokkan ke cve_entries dengan batas lima baris, lalu dilengkapi lookup live dan tautan referensi.
MetodePerilaku
is_availablemenolak berkas yang tidak ada atau berukuran di bawah 100 byte, lalu memastikan SELECT COUNT(*) FROM cve_entries lebih dari 0 (modules/cve_intelligence/cve_matcher.py:42-59)
match_technology_cvesLIKE pada technology, description, affected_products, product, dan vendor, urut cvss_score menurun, LIMIT 20 per teknologi, lalu menyaring dengan severity_min (modules/cve_intelligence/cve_matcher.py:372-410)
get_payloads_from_cvesmemetakan exploit_type ke delapan keranjang payload dan menghapus duplikat dengan dict.fromkeys (modules/cve_intelligence/cve_matcher.py:450-465)
_search_terms_for_typemencari fragmen tipe pada _TYPE_TERMS, dengan fallback token pertama minimal tiga karakter (modules/cve_intelligence/cve_matcher.py:493-502)
enrich_vulnerabilityquery description LIKE ? yang digabung OR, urut cvss_score menurun, LIMIT 5 (modules/cve_intelligence/cve_matcher.py:504-530)
_live_enrichlookup NVD dan GitHub bila live_config["enabled"] (modules/cve_intelligence/cve_matcher.py:571-582)

_TYPE_TERMS menjadi kamus kecil antara tipe temuan dan pola SQL, misalnya:

Fragmen tipePola LIKE
sql, sqli%SQL injection%, %SQLi%, %SQL Injection%
xss, cross-site scripting%XSS%, %cross-site scripting%
log4j, log4shell, jndi%Log4j%, %Log4Shell%, %JNDI%

enrich_vulnerability menulis related_cves (deskripsi dipotong 150 karakter), menambahkan id baru ke cve_references, lalu menandai cve_matched = True; kegagalan query hanya dicatat pada level debug (modules/cve_intelligence/cve_matcher.py:551-569). Setelah itu _live_enrich dipanggil dan hasil akhirnya diberi tautan NVD, Exploit-DB, dan GitHub lewat _attach_links_only, yang mengisi cve_links per cve_id (modules/cve_intelligence/cve_matcher.py:648-663).

Live lookup opsional

sequenceDiagram
  participant E as enrich_vulnerability
  participant L as _live_enrich
  participant N as NVD 2.0 API
  participant G as GitHub Search
  participant A as _attach_links_only
  E->>L: dict temuan
  alt live_config.enabled false
    L->>A: tautkan referensi saja
  else live aktif
    L->>N: nvd_get_cve untuk refs[:3]
    N-->>L: cve_id, severity, cvss_score, links
    L->>N: nvd_search_keyword bila related kosong
    N-->>L: hit keyword
    L->>G: github_search_repos cve atau keyword
    G-->>L: cve_github_pocs
    L->>A: related_cves[:8], cve_references[:12]
  end
  A-->>E: cve_links per cve_id
%% fig: Siklus satu panggilan live lookup
%% desc: enrich_vulnerability memilih jalur tautan saja atau lookup NVD dan GitHub, lalu hasilnya dipangkas dan dilengkapi tautan referensi.
Fig. 3: Siklus satu panggilan live lookupenrich_vulnerability memilih jalur tautan saja atau lookup NVD dan GitHub, lalu hasilnya dipangkas dan dilengkapi tautan referensi.

Ketiga sumber tautan dibentuk oleh attach_reference_links, yang mengembalikan nvd, exploit_db, dan github_poc untuk id berawalan CVE- (modules/cve_intelligence/live_lookup.py:37-45). Semua panggilan NVD melewati _throttle dengan jeda minimum 0,6 detik, dan respons disimpan pada _cache per kunci kw: atau id: sehingga pengulangan tidak menembak API lagi (modules/cve_intelligence/live_lookup.py:52-58). nvd_search_keyword memotong keyword pada 200 karakter, membatasi resultsPerPage antara 1 dan 20, memakai timeout=25, dan mengembalikan daftar kosong untuk status selain 200 (modules/cve_intelligence/live_lookup.py:61-99).

github_search_repos menyusun query {keyword} exploit OR poc OR vulnerability, mengurutkan berdasarkan bintang, membatasi per_page antara 1 dan 10, dan mengembalikan full_name, stars, url, description, serta language (modules/cve_intelligence/live_lookup.py:147-175). nvd_get_cve mengembalikan None untuk id yang tidak berawalan CVE- dan menormalkan metrik lewat _normalize_nvd_item (modules/cve_intelligence/live_lookup.py:105-131). Bila lokal tidak menemukan apa pun, keyword_from_finding memakai CVE id yang tertangkap dari evidence lebih dulu, lalu menyusun keyword dari type dan parameter dengan maksimum enam token (modules/cve_intelligence/live_lookup.py:247-262).

Titik pemakaian saat scan

ScannerEngine membuat matcher hanya bila experimental.enable_cve_matching bernilai benar, lalu memanggil get_cve_matcher(config, auto_seed=True); bila DB tidak tersedia dan live lookup mati, factory mengembalikan None dan engine mencatat saran menjalankan python scripts/update_cve_database.py (core/scanner_engine.py:219-239).

Factory get_cve_matcher menyusun live_config dari experimental maupun cve_intelligence dengan default max_results 3, keyword_search dan github_search benar, fetch_cve_detail benar, serta always_keyword_search salah, lalu seed DB dengan ensure_seed_if_empty(min_rows=5) sebelum memutuskan matcher layak dipakai (modules/cve_intelligence/cve_matcher.py:678-727). Path DB diresolusi resolve_cve_db_path dengan prioritas experimental.cve_database_path, lalu cve_intelligence.database_path, lalu data/cve_intelligence.db (modules/cve_intelligence/cve_matcher.py:666-675).

Setelah pemindaian satu URL mengumpulkan temuan, engine memanggil enrich_vulnerability untuk setiap item dan mencatat Enriched {len(vulnerabilities)} vulnerabilities with CVE data (core/scanner_engine.py:588-595). Generator payload juga memakai matcher: match_technology_cves(tech_stack) lalu get_payloads_from_cves, dan payload CVE ditempatkan di depan dengan batas lima item per tipe serangan (core/ai_payload_generator.py:112-122).

Pengayaan RAG berjalan terpisah setelah scan, di gerbang rag.enabled: engine memanggil rag.is_stale, membangun dan menyimpan index bila usang dan auto_rebuild aktif, atau memanggil rag.load; setelah itu setiap temuan yang belum punya cve_references diisi id hasil rag.search dan ditandai rag_matched (core/scanner_engine.py:878-910). Query-nya adalah gabungan type, parameter, dan 200 karakter pertama evidence, dengan top_k dari rag.top_k (default 3) (core/scanner_engine.py:895-907).

⚠️ Dua jalur itu tidak memakai resolver path yang sama. Matcher mengikuti experimental.cve_database_path (modules/cve_intelligence/cve_matcher.py:666-675), sedangkan langkah RAG membaca cve_intelligence.database_path dengan default data/cve_intelligence.db (core/scanner_engine.py:884-886). Bila path khusus hanya diisi pada experimental, is_stale membandingkan pickle dengan berkas default; ketika berkas default tidak ada, is_stale mengembalikan False dan index lama tetap dipakai walaupun basis data sebenarnya sudah diperbarui (modules/cve_intelligence/rag_index.py:68-74).

Blok rag: sendiri tidak ada di berkas contoh; yang didokumentasikan hanya kunci experimental.* untuk CVE intelligence, termasuk cve_live_lookup, nvd_api_key, dan github_token (config/config.example.yaml:593-611). Rincian gerbang dan urutan fase scan ada di Alur Scan.