
Strumento di rilevamento e mitigazione delle vulnerabilità per i bug Copy Fail e Dirty Frag (CVE-2026-31431, CVE-2026-43284, CVE-2026-43500)
# vcheck Controlla un host Linux remoto via SSH per le vulnerabilità dei moduli del kernel Copy Fail e Dirty Frag e, opzionalmente, applica le mitigazioni: | CVE | Name | Moduli interessati | | -------------- | ------------------ | ------------------------------------------------- | | CVE-2026-31431 | Copy Fail | `algif_aead` | | CVE-2026-43284 | Dirty Frag (IPsec) | `esp4`, `esp6`, `ipcomp4`, `ipcomp6`, `xfrm_user` | | CVE-2026-43500 | Dirty Frag (RxRPC) | `rxrpc`, `kafs` | Per ogni modulo interessato, vcheck segnala se è attualmente caricato, se è compilato nel kernel in esecuzione, se ci sono tracce passate nei log del kernel, se ci sono socket `AF_ALG` attivi (solo per Copy Fail) e se è già in blacklist in `/etc/modprobe.d/`. Con `-fix`, vcheck riporta lo stato iniziale, scrive un file `cve-XXXX-XXXXX-disable.conf` per ogni modulo non ancora in blacklist, quindi riesegue i controlli e riporta lo stato finale. Con `-fix -unload`, vcheck tenta anche di scaricare i moduli interessati già caricati prima della correzione, quindi usa la scansione finale per verificare se sono ancora caricati. Con `-fix -rebuild-initramfs`, vcheck ricostruisce l'initramfs per il kernel attualmente in esecuzione (solo) dopo la scrittura di un file, in modo che la blacklist venga inclusa nella prossima immagine di avvio. Le voci del kernel meno recenti mantengono il loro initramfs originale come ripiego. ## Usa `-fix` solo dopo un'esecuzione di solo controllo **Esegui sempre vcheck prima senza `-fix`.** Leggi il rapporto e conferma che i moduli interessati possano essere disabilitati in sicurezza su questo host prima di rieseguire con `-fix`. Disabilitare moduli del kernel da cui dipendono workload legittimi può avere impatto sugli utenti e rompere le applicazioni. In particolare: - Considera `-fix` sicuro **solo** quando nessuno dei moduli interessati è attualmente caricato — cioè ogni modulo è segnalato come `mitigated` o `module not blacklisted` (nessuna riga `VULNERABLE` o `blacklisted but currently loaded`). Un modulo caricato significa quasi sempre che _qualcosa sull'host lo sta usando attivamente_; verificalo prima di metterlo in blacklist. - I moduli IPsec (`esp4`, `esp6`, `ipcomp4`, `ipcomp6`, `xfrm_user`) sono necessari per qualsiasi implementazione IPsec/strongSwan/WireGuard-over-IPsec/IKE. I moduli `ipcomp4`/`ipcomp6` implementano la compressione del payload IPComp e possono essere negoziati automaticamente come parte di una SA IPsec anche se non configurati esplicitamente. Non metterli in blacklist su un gateway VPN, un endpoint IPsec o ovunque `ip xfrm policy` restituisca regole. Nota che il modulo framework `xfrm_algo` è volutamente **non** in questo elenco — secondo le indicazioni dei vendor (Red Hat, Ubuntu, AWS), bloccare i moduli dei protocolli ESP e IPComp più l'interfaccia di configurazione netlink `xfrm_user` è sufficiente, e mettere in blacklist `xfrm_algo` romperebbe ogni altra trasformazione xfrm senza alcun beneficio aggiuntivo. - I moduli RxRPC (`rxrpc`, `kafs`) sono necessari per qualsiasi host che monta filesystem AFS. Disabilitarli romperà quei mount al prossimo avvio. - `algif_aead` espone la crittografia del kernel tramite la famiglia di socket `AF_ALG`. È usato raramente direttamente dal codice delle applicazioni, ma verifica elencando i socket attivi (`ss -p --af-alg`) e controllando i consumatori in spazio utente prima di metterlo in blacklist. I file di blacklist scritti da vcheck hanno effetto solo al momento del caricamento del modulo (in genere al riavvio successivo, oppure con `modprobe -r <module>` a sistema inattivo). Un modulo _già caricato_ continuerà a funzionare anche dopo `-fix` — vcheck lo segnalerà come `blacklisted but currently loaded; run 'modprobe -r' or reboot`. Passare `-unload` insieme a `-fix` chiede a vcheck di eseguire `modprobe -r` per i moduli interessati caricati dopo la scrittura dei file di blacklist. Usalo solo quando hai confermato che i moduli possono essere rimossi in sicurezza dal kernel in esecuzione. Passare `-rebuild-initramfs` insieme a `-fix` rigenera l'initramfs **solo per il kernel attualmente in esecuzione** (`update-initramfs -u -k $(uname -r)` su Debian/Ubuntu, `dracut -f --kver $(uname -r)` su RHEL/Fedora). Gli altri kernel installati mantengono intatto il proprio initramfs, quindi se qualcosa va storto dopo il riavvio puoi scegliere una voce kernel meno recente dal menu di avvio e recuperare. Le future installazioni del kernel ricostruiscono il proprio initramfs a partire dallo stato corrente di `/etc/modprobe.d/`, quindi la blacklist si propaga automaticamente senza dover rieseguire vcheck. Se non sono presenti né `update-initramfs` né `dracut` (ad es. Arch, Alpine, immagini immutabili), vcheck avvisa e continua — ricostruisci manualmente con lo strumento della distribuzione prima di riavviare. La ricostruzione può richiedere alcuni minuti (soprattutto `dracut` su host con molti driver), il che supererebbe il timeout diagnostico `-command-timeout`. Viene eseguita con un proprio `-initramfs-timeout` (default `10m`), così la ricostruzione ha tutto il tempo necessario mentre i controlli rapidi mantengono il loro budget ridotto. Aumenta `-initramfs-timeout` per hardware lento, oppure passa `0` per disabilitare completamente il timeout. Durante i comandi remoti di lunga durata, vcheck invia richieste keepalive SSH ogni `30s` di default per evitare che i timer di inattività NAT/firewall interrompano la connessione. Regola questo valore con `-ssh-keepalive`, oppure passa `0` per disabilitarlo. ## Installazione **Homebrew (macOS):** ```bash brew install --cask krisiasty/tap/vcheck ``` **Binari precompilati** per Linux, macOS e Windows sono pubblicati nella [pagina delle release](https://github.com/krisiasty/vcheck/releases). **Dal sorgente** (richiede Go 1.26+): ```bash go install github.com/krisiasty/vcheck@latest ``` ## Utilizzo ```text vcheck -host HOST [flags] ``` | Flag | Predefinito | Descrizione | | -------------------- | ------------ | -------------------------------------------------------------------------------------------- | | `-host` | _(obbligatorio)_ | Host remoto | | `-user` | `$USER` | Utente remoto | | `-port` | `22` | Porta SSH remota | | `-agent` | `true` | Usa l'agente SSH per l'autenticazione | | `-identity` | _(vuoto)_ | Percorso di un file di chiave privata (chiede la passphrase se cifrato) | | `-password` | `false` | Chiede una password SSH | | `-insecure` | `false` | Accetta host key non ancora registrate in `known_hosts`; le discrepanze con una chiave registrata falliscono comunque | | `-fix` | `false` | Scrive i file in `/etc/modprobe.d` per i moduli non ancora in blacklist | | `-unload` | `false` | Con `-fix`, scarica i moduli interessati dopo averli messi in blacklist | | `-rebuild-initramfs` | `false` | Con `-fix`, ricostruisce l'initramfs solo per il kernel in esecuzione (`update-initramfs` o `dracut`) | | `-skip-logs` | `false` | Salta i controlli sulla cronologia dei log del kernel | | `-timeout` | `15s` | Timeout di connessione SSH | | `-ssh-keepalive` | `30s` | Intervallo keepalive SSH (`0` lo disabilita) | | `-command-timeout` | `30s` | Timeout dei comandi remoti (`0` lo disabilita) | | `-initramfs-timeout` | `10m` | Timeout per il passaggio di ricostruzione dell'initramfs (`0` lo disabilita); usato solo con `-rebuild-initramfs` | | `-debug` | `false` | Aumenta la verbosità dei log | | `-version` | `false` | Mostra la versione ed esce | Almeno uno tra `-agent`, `-identity` o `-password` deve produrre un metodo di autenticazione utilizzabile. I metodi vengono provati nell'ordine elencato. Sudo è richiesto sull'host di destinazione. Se è configurato sudo senza password, lo strumento procede silenziosamente; altrimenti chiede una volta la password (l'input è nascosto) e la fornisce tramite `sudo -S` per ogni comando successivo. ## Codici di uscita | Codice | Significato | | ------ | ---------------------------------------------------------------------------------- | | `0` | Tutti i moduli interessati in blacklist, scaricati, non compilati nel kernel e inattivi | | `1` | Errore di utilizzo | | `2` | Connessione SSH fallita | | `3` | Autenticazione sudo fallita | | `4` | Uno o più moduli non in blacklist (nessuna esposizione attuale) | | `5` | Uno o più moduli attualmente caricati, compilati nel kernel o in uso attivo | | `99` | Errore interno/di controllo | ## Esempio di output ### Host completamente mitigato ```console $ vcheck -host host.example.com -identity ~/.ssh/id_ed25519 INF connected user=ops host=host.example.com port=22 INF checking vulnerability cve=CVE-2026-31431 name="Copy Fail" INF checking vulnerability cve=CVE-2026-43284 name="Dirty Frag (IPsec)" INF checking vulnerability cve=CVE-2026-43500 name="Dirty Frag (RxRPC)" INF mitigated cve=CVE-2026-31431 module=algif_aead INF mitigated cve=CVE-2026-43284 module=esp4 INF mitigated cve=CVE-2026-43284 module=esp6 INF mitigated cve=CVE-2026-43284 module=ipcomp4 INF mitigated cve=CVE-2026-43284 module=ipcomp6 INF mitigated cve=CVE-2026-43284 module=xfrm_user INF mitigated cve=CVE-2026-43500 module=rxrpc INF mitigated cve=CVE-2026-43500 module=kafs ``` ### Non mitigato e parzialmente caricato — controllo semplice ```console $ vcheck -host host.example.com -identity ~/.ssh/id_ed25519 INF connected user=ops host=host.example.com port=22 INF checking vulnerability cve=CVE-2026-31431 name="Copy Fail" INF checking vulnerability cve=CVE-2026-43284 name="Dirty Frag (IPsec)" INF checking vulnerability cve=CVE-2026-43500 name="Dirty Frag (RxRPC)" INF mitigated cve=CVE-2026-31431 module=algif_aead ERR VULNERABLE cve=CVE-2026-43284 module=esp4 loaded=true ERR module not blacklisted cve=CVE-2026-43284 module=esp6 ERR module not blacklisted cve=CVE-2026-43284 module=ipcomp4 ERR module not blacklisted cve=CVE-2026-43284 module=ipcomp6 ERR module not blacklisted cve=CVE-2026-43284 module=xfrm_user ERR module not blacklisted cve=CVE-2026-43500 module=rxrpc ERR module not blacklisted cve=CVE-2026-43500 module=kafs ``` ### Stesso host con `-fix` — prima esecuzione ```console $ vcheck -fix -host host.example.com -identity ~/.ssh/id_ed25519 INF connected user=ops host=host.example.com port=22 INF checking vulnerability cve=CVE-2026-31431 name="Copy Fail" INF checking vulnerability cve=CVE-2026-43284 name="Dirty Frag (IPsec)" INF checking vulnerability cve=CVE-2026-43500 name="Dirty Frag (RxRPC)" INF findings before fix INF mitigated cve=CVE-2026-31431 module=algif_aead ERR VULNERABLE cve=CVE-2026-43284 module=esp4 loaded=true ERR module not blacklisted cve=CVE-2026-43284 module=esp6 ERR module not blacklisted cve=CVE-2026-43284 module=ipcomp4 ERR module not blacklisted cve=CVE-2026-43284 module=ipcomp6 ERR module not blacklisted cve=CVE-2026-43284 module=xfrm_user ERR module not blacklisted cve=CVE-2026-43500 module=rxrpc ERR module not blacklisted cve=CVE-2026-43500 module=kafs INF writing modprobe.d snippet path=/etc/modprobe.d/cve-2026-43284-disable.conf modules="[esp4 esp6 ipcomp4 ipcomp6 xfrm_user]" INF writing modprobe.d snippet path=/etc/modprobe.d/cve-2026-43500-disable.conf modules="[rxrpc kafs]" INF re-scanning after fix snippets_written=2 INF checking vulnerability cve=CVE-2026-31431 name="Copy Fail" INF checking vulnerability cve=CVE-2026-43284 name="Dirty Frag (IPsec)" INF checking vulnerability cve=CVE-2026-43500 name="Dirty Frag (RxRPC)" INF findings after fix INF mitigated cve=CVE-2026-31431 module=algif_aead ERR blacklisted but currently loaded; run 'modprobe -r' or reboot cve=CVE-2026-43284 module=esp4 INF mitigated cve=CVE-2026-43284 module=esp6 INF mitigated cve=CVE-2026-43284 module=ipcomp4 INF mitigated cve=CVE-2026-43284 module=ipcomp6 INF mitigated cve=CVE-2026-43284 module=xfrm_user INF mitigated cve=CVE-2026-43500 module=rxrpc INF mitigated cve=CVE-2026-43500 module=kafs ``` La blacklist è in atto, ma `esp4` era già caricato nel kernel prima della scrittura del file. Riavvia o esegui `sudo modprobe -r esp4` sull'host per eliminarlo completamente. ### Seconda esecuzione — esp4 ancora caricato ```console $ vcheck -fix -host host.example.com -identity ~/.ssh/id_ed25519 INF connected user=ops host=host.example.com port=22 INF checking vulnerability cve=CVE-2026-31431 name="Copy Fail" INF checking vulnerability cve=CVE-2026-43284 name="Dirty Frag (IPsec)" INF checking vulnerability cve=CVE-2026-43500 name="Dirty Frag (RxRPC)" INF findings before fix INF mitigated cve=CVE-2026-31431 module=algif_aead ERR blacklisted but currently loaded; run 'modprobe -r' or reboot cve=CVE-2026-43284 module=esp4 INF mitigated cve=CVE-2026-43284 module=esp6 INF mitigated cve=CVE-2026-43284 module=ipcomp4 INF mitigated cve=CVE-2026-43284 module=ipcomp6 INF mitigated cve=CVE-2026-43284 module=xfrm_user INF mitigated cve=CVE-2026-43500 module=rxrpc INF mitigated cve=CVE-2026-43500 module=kafs INF fix: nothing to do — all affected modules already blacklisted ``` ### Terza esecuzione — dopo `modprobe -r esp4` ```console $ vcheck -host host.example.com -identity ~/.ssh/id_ed25519 INF connected user=ops host=host.example.com port=22 INF checking vulnerability cve=CVE-2026-31431 name="Copy Fail" INF checking vulnerability cve=CVE-2026-43284 name="Dirty Frag (IPsec)" INF checking vulnerability cve=CVE-2026-43500 name="Dirty Frag (RxRPC)" INF mitigated cve=CVE-2026-31431 module=algif_aead INF mitigated cve=CVE-2026-43284 module=esp4 INF mitigated cve=CVE-2026-43284 module=esp6 INF mitigated cve=CVE-2026-43284 module=ipcomp4 INF mitigated cve=CVE-2026-43284 module=ipcomp6 INF mitigated cve=CVE-2026-43284 module=xfrm_user INF mitigated cve=CVE-2026-43500 module=rxrpc INF mitigated cve=CVE-2026-43500 module=kafs ``` ### Con `-rebuild-initramfs` ```console $ vcheck -fix -rebuild-initramfs -host host.example.com -identity ~/.ssh/id_ed25519 ... INF writing modprobe.d snippet path=/etc/modprobe.d/cve-2026-43284-disable.conf modules="[esp4 esp6 ipcomp4 ipcomp6 xfrm_user]" INF writing modprobe.d snippet path=/etc/modprobe.d/cve-2026-43500-disable.conf modules="[rxrpc kafs]" INF rebuilding initramfs for running kernel timeout=10m0s INF initramfs rebuilt for running kernel tool=update-initramfs INF re-scanning after fix snippets_written=2 ... ``` Viene ricostruito solo l'initramfs del kernel in esecuzione. Gli altri kernel installati mantengono il proprio initramfs, quindi una voce meno recente nel menu di avvio resta un ripiego funzionante se il nuovo initramfs causa problemi. Su un host senza né `update-initramfs` né `dracut`, vcheck registra `WRN no supported initramfs tool found ...` e continua. ### Primo contatto con l'host — `-insecure` ```console $ vcheck -insecure -host host.example.com -identity ~/.ssh/id_ed25519 WRN host key not in known_hosts; accepting due to -insecure host=host.example.com:22 remote=192.0.2.42:22 fingerprint=SHA256:AAAAEXAMPLEfingerPrint000000000000000000000 INF connected user=ops host=host.example.com port=22 INF checking vulnerability cve=CVE-2026-31431 name="Copy Fail" ... ``` `-insecure` accetta host non ancora presenti in `known_hosts`. Se un host _è_ già registrato e presenta una chiave diversa, la connessione fallisce comunque — il flag è solo una deroga per il "primo contatto", non un modo per sopprimere gli avvisi man-in-the-middle su un host noto. ## Dettagli del rilevamento - **Caricato:** `lsmod` viene recuperato una volta e i nomi dei moduli vengono confrontati con la prima colonna. - **Compilato nel kernel:** vengono controllati `/lib/modules/$(uname -r)/modules.builtin` e `/sys/module`, perché i file di modprobe non possono disabilitare codice compilato nel kernel in esecuzione. - **In blacklist:** viene cercato in ogni file sotto `/etc/modprobe.d/` (`grep -rE`) una direttiva `install <module> /bin/false` — la stessa forma che vcheck scrive con `-fix`. Altre forme di disabilitazione (ad es. `blacklist`) non vengono riconosciute. - **Attività passata:** viene consultato prima `journalctl -k`, con ripiego su `/var/log/kern.log`; vengono conservate le ultime cinque righe corrispondenti per ogni modulo. Passa `-skip-logs` per saltare questo passaggio. - **Socket attivi (solo `algif_aead`):** `ss -p --af-alg` elenca i socket `AF_ALG` aperti; qualsiasi output diverso dall'intestazione conta come utilizzo attivo. Tutti i comandi vengono eseguiti tramite `sudo` e sono limitati da `-command-timeout` — l'accesso privilegiato è necessario per leggere `/var/log/kern.log`, elencare i socket `AF_ALG` e scrivere in `/etc/modprobe.d/`. Con `-unload`, l'accesso privilegiato è necessario anche per eseguire `modprobe -r`. Con `-rebuild-initramfs`, vcheck esegue `update-initramfs -u -k $(uname -r)` (Debian/Ubuntu) o `dracut -f --kver $(uname -r)` (RHEL/Fedora), che richiedono anch'essi i permessi di root.