Torna agli aggiornamenti
New releaseJul 24, 2026

fleet-cve-scanner v1.1.0

Uno scanner CVE open-source e a script singolo per flotte gestite con RMM. Puro PowerShell 7 — unisce l'inventario software del tuo RMM con NVD, CISA KEV, EPSS e SSVC per rispondere: questa versione è vulnerabile e quanto è urgente?

Condividi

fleet-cve-scanner

Uno scanner CVE open-source e a script singolo per flotte gestite tramite RMM. Puro PowerShell 7, senza agenti, senza appliance, senza costi di licenza.

Risponde a una domanda per ogni software su ogni endpoint che gestisci: la versione installata è nota come vulnerabile e quanto è urgente? — unendo l'inventario software del tuo RMM con feed di sicurezza gratuiti e autorevoli:

  • NIST NVD — CVE note + intervalli di versione interessati
  • CISA KEV — sfruttate attivamente in libertà (supera la soglia del punteggio)
  • EPSS — probabilità di sfruttamento nei prossimi 30 giorni
  • CISA SSVC — decisioni di priorità agisci / presidia / monitora
  • MSRC — prova che una patch Microsoft copre già la scoperta
  • endoflife.date — software che non riceverà più patch

Output: un report CSV per dispositivo, uno storico SQLite con orologi SLA ed eventi di modifica settimana su settimana, un dashboard HTML autonomo e un report opzionale in markdown sulle esposizioni.

Stato

v1.0.0. Il motore è stato portato da zero da uno scanner eseguito settimanalmente in produzione su una flotta Windows (vedi docs/HISTORY.md). Prima di questo rilascio, i due sono stati eseguiti sulla stessa flotta live e confrontati riga per riga: su decine di migliaia di rilevamenti in cui entrambi vedevano lo stesso (dispositivo, software, versione), ogni campo calcolato — stato, CVSS, gravità, flag KEV, decisione SSVC, versione di fix — corrispondeva esattamente.

Tale confronto copre la logica di verdetto. Non ha esercitato il livello storico/SLA e non sostituisce la validazione dello strumento nel tuo ambiente. Leggi docs/known-limitations.md prima di fidarti — è scritto per essere onesto, non lusinghiero.

Avvio rapido

Ti serve PowerShell 7 (pwsh). Due modi per eseguirlo:

A. Scansione NinjaOne live

cp config.example.json config.json
# modifica config.json: inserisci ninjaone.client_id / client_secret / base_url,
# imposta output.report_dir e (consigliato) nvd.api_key
pwsh -File fleet-cve-scan.ps1

B. Offline — qualsiasi RMM, SCCM o Intune (nessun accesso API)

Esporta il tuo inventario in un CSV con colonne hostname, software, version (opzionale device_id, os), quindi:

cp config.example.json config.json   # qui serve solo output.report_dir
pwsh -File fleet-cve-scan.ps1 -InputCsv inventory.csv

-InputCsv non effettua nessuna chiamata NinjaOne — niente OAuth, niente API. Interroga comunque NVD e gli altri feed pubblici, quindi ti serve comunque un nvd.api_key in config.json e un output.report_dir valido. Vedi docs/rmm-adapters.md per il contratto di input e le ricette di esportazione per RMM specifici.

Installazione dei prerequisiti

  • PowerShell 7 — macOS: brew install powershell; Windows: winget install Microsoft.PowerShell; Debian/Ubuntu: installa dal repository dei pacchetti Microsoft (packages.microsoft.com).
  • sqlite3 (opzionale, abilita storico/trend) — macOS: preinstallato o brew install sqlite; Debian/Ubuntu: apt-get install sqlite3; Windows: scarica il bundle "tools" di SQLite da sqlite.org e metti sqlite3.exe nel PATH o accanto allo script. Senza di esso la scansione funziona comunque; first_seen viene impostato alla data di esecuzione.

Requisiti

  • PowerShell 7 (7.4+ consigliato). La scansione parallela richiede 7.0+.
  • sqlite3 — opzionale; abilita il DB storico, i trend e il tracciamento SLA first_seen. Se assente = quelle funzionalità vengono saltate, la scansione completa comunque.
  • Traffico di rete in uscita verso NVD, CISA (KEV), epss.empiricalsecurity.com (l'host del punteggio bulk EPSS — FIRST ha spostato lì l'hosting dei dati EPSS), MSRC, endoflife.date e raw.github.com (CVE Program cvelistV5) — oltre all'API NinjaOne in modalità live.
  • Credenziali — modalità live necessita di client id/secret OAuth2 di NinjaOne; modalità offline necessita solo di un CSV di inventario. Una chiave API NVD è tecnicamente opzionale ma di fatto richiesta a scala di flotta: NVD consente 50 richieste/30s con chiave e solo 5/30s senza. Lo scanner rileva quale hai e si adatta di conseguenza, quindi un'esecuzione senza chiave è corretta ma circa 10x più lenta — va bene per una manciata di prodotti, impraticabile per una flotta reale. Le chiavi sono gratuite.

Riferimento configurazione

La configurazione è un file JSON (predefinito config.json accanto allo script; sovrascrivere con -ConfigPath). Inizia da config.example.json. Ogni chiave che lo scanner legge, il suo valore predefinito quando omessa e cosa fa:

ninjaone (modalità live)

ChiavePredefinitoScopo
ninjaone.client_id""ID client OAuth2 API NinjaOne. Richiesto per scansioni live; lascia vuoto per -InputCsv.
ninjaone.client_secret""Segreto client OAuth2 API NinjaOne.
ninjaone.base_url— (l'esempio fornisce https://app.ninjarmm.com)URL base API NinjaOne; richiesto per scansioni live, nessun fallback predefinito. Usa l'host della tua regione (es. eu.ninjarmm.com, oc.ninjarmm.com).

nvd

ChiavePredefinitoScopo
nvd.api_key""Chiave API NVD, inviata come header apiKey. Vuota esegue autenticazione non autenticata, che abbassa i valori predefiniti per nvd_rate_limit e nvd_min_spacing_ms al limite anonimo di NVD (4/30s, 6500ms) invece di quello autenticato (48/30s, 700ms). Gratuito e ~10x più veloce.

Scansione e punteggio

ChiavePredefinitoScopo
cvss_threshold7.0Punteggio base CVSS minimo affinché un CVE con punteggio venga segnalato come VULNERABILE. I CVE presenti nell'elenco KEV bypassano questa soglia.
ssvc_mission_prevalencehighInput stakeholder SSVC Mission Prevalence (low / medium / high).
ssvc_public_wellbeinghighInput stakeholder SSVC Public Well-being (low / medium / high).

Caching e limitazione della velocità

ChiavePredefinitoScopo
nvd_cache_ttl_days7Giorni in cui un risultato NVD (per nome software) rimane nella cache prima di essere richiesto nuovamente.
nvd_cache_flush_every500Punto di controllo della cache NVD su disco ogni N elementi completati, in modo che una scansione interrotta mantenga i dati recuperati. 0 disabilita (il salvataggio a fine scansione viene comunque eseguito).
nvd_min_spacing_ms700 con chiave API, 6500 senzaMillisecondi minimi tra chiamate NVD. Il vincolo di velocità fondamentale — regola prima questo.
nvd_rate_limit48 con chiave API, 4 senzaLimite massimo di chiamate NVD per 30s (una protezione). Minimo 1.
parallel_throttle20Conteggio runspace ForEach-Object -Parallel. Le chiamate NVD sono comunque serializzate; questo limita solo la concorrenza dei cache-hit. Minimo 1.
kev_cache_ttl_hours24TTL per il catalogo CISA KEV memorizzato nella cache.
epss_cache_ttl_hours24TTL per il file dei punteggi EPSS di FIRST.org memorizzato nella cache.
eol_cache_ttl_days7TTL per le ricerche endoflife.date memorizzate nella cache.
msrc_cache_ttl_days30TTL per i dati CVRF di MSRC memorizzati nella cache.
cvelist_cache_ttl_days7TTL per i dati SSVC di CVE Program (cvelistV5) / CISA-ADP memorizzati nella cache.
cvelist_fetch_budget300Numero massimo di recuperi di record CVE per esecuzione per l'arricchimento SSVC/vulnrichment; il resto viene rimandato all'esecuzione successiva.

nvd_min_spacing_ms, nvd_rate_limit e parallel_throttle vengono letti dallo scanner ma non sono presenti in config.example.json — aggiungili solo se devi regolarli. Vedi docs/rate-limiting.md.

Arricchimento e SLA

ChiavePredefinitoScopo
epss_spike_threshold0.10Aumento minimo del punteggio EPSS di un rilevamento tra scansioni per generare un evento di modifica EPSS_SPIKE.
sla_days_critical14Finestra SLA (giorni da first_seen) per rilevamenti CRITICI.
sla_days_high30Finestra SLA per altre gravità con punteggio.
denied_software_csv""Percorso per un controllo incrociato opzionale su un CSV di software negato. Vuoto disabilita il controllo.

output

ChiavePredefinitoScopo
output.report_dir(obbligatorio)Directory per tutti gli output: CSV, DB storico, dashboard e cache.
output.wiki_security_page""Percorso opzionale per una pagina di esposizione in markdown. Viene scritta solo quando impostato.
output.dashboard_share""Percorso/condivisione opzionale che riceve una copia del dashboard a ogni esecuzione. Vuoto = solo locale.

Output

Tutto quanto segue viene inserito in output.report_dir.

  • vuln-report-YYYY-MM-DD.csv — il report per rilevamento. 28 colonne (schema sotto).
  • vuln-history.db — storico SQLite (richiede sqlite3): runs (aggregati per esecuzione), findings (storico dei rilevamenti aperti per (device, software, cve) con first_seen / last_seen / resolved_date / epss_score) e changes (eventi settimana su settimana tipizzati).
  • cve-dashboard.html — dashboard HTML autonomo (libreria grafica incorporata, nessuna richiesta esterna). Opzionalmente copiato in output.dashboard_share.
  • eol-report-YYYY-MM-DD.csv — scritto quando vengono rilevate famiglie a fine vita.
  • denied-report-YYYY-MM-DD.csv — scritto quando denied_software_csv è configurato e corrisponde.
  • File di cachenvd-cache.json, kev-cache.json, epss-cache.json, eol-cache.json, msrc-cache.json, cvelist-cache.json (tutti in gitignore).
  • Pagina di esposizione in markdown — in output.wiki_security_page, solo quando impostato.

Schema CSV (28 colonne)

Il set di colonne è fisso e controllato al gate. In ordine:

#ColonnaSignificato
1device_idID dispositivo RMM (o un ID sintetico deterministico in modalità -InputCsv).
2hostnameNome host del dispositivo.
3osStringa del sistema operativo (può essere vuota).
4softwareNome del prodotto come inventariato.
5installed_versionStringa della versione come inventariata.
6cve_idIdentificatore CVE.
7cvss_scorePunteggio base CVSS (0 se assente).
8severityEtichetta di gravità CVSS.
9cvss_versionQuale standard CVSS ha prodotto il punteggio (4.0/3.1/3.0/2.0/vuoto).
10epss_scoreProbabilità FIRST.org EPSS (vuoto se il CVE è assente dal catalogo).
11epss_percentilePercentile EPSS (vuoto se assente).
12ssvc_exploitationOpzione di sfruttamento SSVC CISA grezza (none/poc/active; vuoto senza dati ADP).
13ssvc_decisionDecisione SSVC Act/Attend/Track (vuoto senza dati ADP).
14statusVULNERABLE / PATCHED / UNKNOWN.
15published_dateData di pubblicazione CVE.
16unknown_reasonPerché una riga è UNKNOWN (SUSPECT_VERSION / NO_VERSION_BOUND / VERSION_PARSE_ERROR; vuoto altrimenti).
17is_kevTrue quando il CVE è nel catalogo KEV di CISA.
18kev_due_dateData di scadenza della bonifica KEV di CISA.
19kev_ransomware_useFlag di utilizzo in campagne ransomware KEV.
20fix_versionVersione calcolata del confine di fix.
21fix_boundary_inclusiveSe il confine di fix è inclusivo.
22advisory_urlURL del bollettino del fornitore o dettagli NVD.
23patch_evidenceEvidenza quando un UNKNOWN Microsoft è stato trasformato in PATCHED.
24triage_statusDisposizione di triage da triage.json (vuoto se nessuno).
25triage_noteNota di triage.
26first_seenData in cui il rilevamento è stato osservato per la prima volta (dal DB storico).
27sla_dueData di scadenza SLA.
28sla_breachSe lo SLA è stato violato.

Programmazione

Run-WeeklyScan.ps1 è un wrapper per esecuzioni programmate: esegue lo scanner dalla propria directory, cattura tutti i flussi di output in un log datato sotto <script dir>/logs/ (sovrascrivibile con -LogDir) e propaga il codice di uscita dello scanner in modo che il programmatore veda gli errori.

Utilità di pianificazione di Windows:

schtasks /Create /TN "CVE-Scan-Weekly" ^
  /TR "pwsh -NoProfile -File C:\path\to\Run-WeeklyScan.ps1" ^
  /SC WEEKLY /D SUN /ST 22:00 /RU SYSTEM

cron (Linux/macOS):

0 22 * * 0  pwsh -File /path/to/Run-WeeklyScan.ps1

Hosting del dashboard

cve-dashboard.html è completamente autonomo — aprilo direttamente, posizionalo su qualsiasi host statico o condivisione file, oppure copialo automaticamente a ogni esecuzione tramite output.dashboard_share. Per hosting con controllo degli accessi, la directory dashboard-auth/ include un host ASP.NET minimale con autenticazione Microsoft Entra (Azure AD); consulta il suo README e RUNBOOK.

Limitazioni oneste (leggere prima di fidarsi)

  • Il matching CPE è per natura fuzzy. Il 40–60% di un inventario tipico non ha alcuna voce NVD e viene saltato (registrato, mai silenziosamente). La selezione CPE basata sul nome può scegliere il prodotto sbagliato; esiste un flusso di lavoro di soppressione perché è necessario. Questo è il limite dell'approccio NVD gratuito — uno scanner a pagamento con un catalogo di rilevamento curato sarà più accurato. Il valore di questo strumento è essere gratuito, trasparente e verificabile.
  • UNKNOWN è un verdetto di prima classe. Quando lo scanner non può provare vulnerabile-o-patched, lo dice invece di indovinare.
  • Verificato solo contro NinjaOne. Il motore di scansione è indipendente dall'RMM (l'input è solo dispositivo + software + versione); la modalità -InputCsv consente a qualsiasi esportazione RMM/SCCM/Intune di alimentarlo, ma solo l'adattatore NinjaOne è stato eseguito in produzione.

L'elenco completo e senza sconti — il tasso di skip CPE, il mascheramento delle chiavi di deduplicazione, totalResults di pagina 1, le lacune di supersedenza MSRC e altro — si trova in docs/known-limitations.md.

Note di progettazione

Alcune scelte strutturali che sembrano non convenzionali sono intenzionali:

  • File singolo, non un modulo. Il percorso critico della scansione viene eseguito all'interno di ForEach-Object -Parallel e questi runspace non possono vedere funzioni dello scope esterno — motivo per cui una manciata di helper viene intenzionalmente duplicata all'interno del blocco parallelo. Un layout modulare con una funzione per file non rimuoverebbe quella duplicazione (il corpo parallelo avrebbe comunque bisogno del sorgente iniettato per ogni runspace); aggiungerebbe solo un passaggio di build e romperebbe il modello di distribuzione a file singolo. Se il progetto supererà mai il file singolo, il packaging è la modifica a forma di v2, non una patch.
  • Record [PSCustomObject], non classi. I record di rilevamento vengono prodotti all'interno di runspace paralleli e restituiti al runspace principale. Le istanze di classe PowerShell non sopravvivono in modo affidabile a quel confine; [PSCustomObject] sì, e il contratto delle colonne CSV viene imposto dal gate di rilascio invece che da un sistema di tipi.
  • Script di test PS7 puri, non Pester. Le suite in tests/ sono script senza dipendenze con asserzioni basate sul codice di uscita, eseguibili ovunque esista pwsh — incluso il server di scansione — senza installare nulla. La CI li esegue tutti su Windows e Ubuntu.

Documentazione

  • docs/how-it-works.md — la pipeline di scansione fase per fase, logica di verdetto, disciplina della cache e contratto di fallimento graduale.
  • docs/known-limitations.md — ogni modo noto in cui lo scanner può sbagliare e perché.
  • docs/rate-limiting.md — le lezioni sui limiti di velocità NVD come guida per l'operatore e tabella di regolazione.
  • docs/rmm-adapters.md — il contratto di input, i due percorsi di inventario predefiniti e come aggiungere un adattatore nativo.
  • docs/HISTORY.md — cronologia delle versioni condensata e ripulita e le lezioni ingegneristiche dietro ogni rilascio.

Contribuire

PR benvenuti — gli adattatori RMM più di tutti. Vedi CONTRIBUTING.md per le regole di base e il requisito di direzione sicura (la logica di stato può solo tendere a una maggiore visibilità, mai silenziosamente verso PATCHED).

Fonti dati e attribuzione

Questo strumento è utile solo quanto i feed gratuiti e autorevoli a cui si collega. Ciascuno dei seguenti viene interrogato al momento della scansione; per favore rispetta i loro termini se costruisci su questo.

  • NIST National Vulnerability Database (NVD) — record CVE e intervalli di versione interessati, tramite API NVD. Questo prodotto utilizza l'API NVD ma non è approvato o certificato dalla NVD. https://nvd.nist.gov/
  • Catalogo delle vulnerabilità note sfruttate (KEV) di CISA — l'elenco autorevole dei CVE noti per essere sfruttati in libertà. https://www.cisa.gov/known-exploited-vulnerabilities-catalog
  • CVE Program — cvelistV5 — record CVE più i dati SSVC / vulnrichment contribuiti da CISA ADP. CVE® è un marchio registrato di The MITRE Corporation. https://github.com/CVEProject/cvelistV5
  • SSVC (Stakeholder-Specific Vulnerability Categorization) — la logica delle decisioni agisci / presidia / monitora in questo strumento deriva da CERT/CC SSVC (Carnegie Mellon University Software Engineering Institute) e dall'albero decisionale SSVC Coordinator di CISA, versione 2.0.3. È richiesto il riconoscimento a CERT/CC e CISA. https://www.cisa.gov/ssvc · https://github.com/CERTCC/SSVC
  • FIRST.org EPSS (Exploit Prediction Scoring System) — probabilità di sfruttamento nei prossimi 30 giorni. I dati EPSS sono forniti da FIRST. Vedi Jay Jacobs, Sasha Romanosky, Benjamin Edwards, Michael Roytman, Idris Adjerid (2021), Exploit Prediction Scoring System, Digital Threats: Research and Practice, 2(3). https://www.first.org/epss/
  • Microsoft Security Response Center (MSRC) — l'API CVRF, utilizzata per confermare quando un aggiornamento di sicurezza Microsoft copre già un rilevamento. © Microsoft Corporation. https://api.msrc.microsoft.com/ · https://msrc.microsoft.com/
  • endoflife.date — date di fine vita e fine del supporto per software che non riceveranno più patch. Dati per gentile concessione del progetto endoflife.date. https://endoflife.date/

Licenza

Apache-2.0 — vedi LICENSE.

Categorie