Guide

Go 1.27.3 e 1.26.10 contro il bug eMudhra: comandi per aggiornare e ricompilare su Ubuntu 24.04

Guida pratica per passare a Go 1.27.3 o 1.26.10 su Ubuntu 24.04, ricompilare i binari e verificare il blocco delle CA eMudhra compromesse (CVE-2026-111943).

Redazione UptimeMag · 2 novembre 2026 · 5 minuti di lettura

Go 1.27.3 e 1.26.10 contro il bug eMudhra: comandi per aggiornare e ricompilare su Ubuntu 24.04

Chi ha letto la notizia del mattino sa già che Go 1.27.3 e 1.26.10 bloccano otto CA intermedie eMudhra con chiavi private deboli (CVE-2026-111943). Qui ci sono i comandi, testati su Ubuntu 24.04 LTS (noble), per passare dalla notizia alla macchina sistemata.

1. Controllare cosa gira ora

go version

Se la riga riporta go1.27.2, go1.26.9 o qualunque versione precedente, il toolchain è vulnerabile. Ma il dato che conta di più è un altro: la versione con cui è stato compilato ogni binario in produzione, non quella installata sulla macchina di build. Si controlla così:

go version -m /percorso/del/binario

Il flag -m stampa i metadati embedded, compresa la versione del compilatore usata. Secondo il blog ufficiale del team Go, si può usare anche go version -m per verificare la versione con cui un binario è stato compilato, e i binari ricompilati con Go 1.27.3 e 1.26.10 rifiuteranno automaticamente i certificati emessi dalle intermedie eMudhra compromesse.

2. Perché l'apt di Ubuntu 24.04 non basta

Prima regola pratica, verificata il 2 novembre 2026 sul repository ufficiale Ubuntu: il pacchetto golang-go in noble è fermo alla versione 2:1.22~2build1, che dipende da golang-1.22-go. Un apt upgrade su Ubuntu 24.04 non porta a 1.27.3 né a 1.26.10, semplicemente perché quella versione non è nei repository standard. Chi gestisce server su questa distribuzione ha due strade praticabili:

Snap ufficiale di Canonical (comodo per chi vuole restare aggiornato senza gestire tarball a mano):

sudo snap install go --classic

Il canale latest/stable dello snap risultava alla versione 1.27.3 alla verifica del 2 novembre 2026.

Tarball ufficiale da go.dev (comodo per CI e ambienti dove si vuole pinnare la versione esatta):

wget https://go.dev/dl/go1.27.3.linux-amd64.tar.gz
sudo rm -rf /usr/local/go
sudo tar -C /usr/local -xzf go1.27.3.linux-amd64.tar.gz
export PATH=$PATH:/usr/local/go/bin

Il file, verificato sulla pagina ufficiale go.dev/dl il 2 novembre 2026, pesa 67MB per l'architettura Linux x86-64. Chi preferisce restare sul ramo 1.26 scarica invece go1.26.10.linux-amd64.tar.gz (64MB), stessa procedura.

Chi tiene più versioni di Go in parallelo (per testare codice su toolchain diversi) può installarne una aggiuntiva senza toccare quella di sistema:

go install golang.org/dl/go1.27.3@latest
go1.27.3 download

e poi richiamarla con go1.27.3 version invece di go version.

3. Il punto che la rubrica del mattino non aveva spazio di spiegare: ricompilare, non solo aggiornare

Il blocco delle CA eMudhra non è un controllo a runtime letto da un file di configurazione: è compilato dentro il binario, nel pacchetto crypto/x509. Significa che:

  • aggiornare go sul server non cambia nulla per i binari già compilati e già in esecuzione;
  • un reverse proxy Go, un agent di monitoring, un tool CLI scritto in Go: se sono stati compilati con un Go precedente al 1.27.3/1.26.10, restano vulnerabili finché non vengono ricompilati e ridistribuiti, anche se la macchina ha il nuovo toolchain installato.

Per ogni progetto Go in produzione, il ciclo minimo è:

cd /percorso/progetto
go build -o nomeapp .
go version -m ./nomeapp

L'ultimo comando deve riportare go1.27.3 o go1.26.10 (o versione successiva) nella riga go dei metadati. Se il progetto gira in container, la ricompilazione va fatta senza cache per evitare che un layer Docker riporti dentro il vecchio toolchain:

docker build --no-cache -t nomeapp:patched .

e nel Dockerfile l'immagine base (golang:1.27.3 o superiore) va aggiornata esplicitamente, non lasciata a un tag mobile tipo golang:1.27 che potrebbe non essere stato ancora ripubblicato dal maintainer dell'immagine.

4. Programma di test: verificare che il rifiuto funzioni davvero

Il modo più diretto per sapere se un binario ricompilato rifiuta davvero le intermedie eMudhra non è fidarsi della versione dichiarata, ma fare un test negativo: un piccolo client TLS che prova a verificare un certificato di test firmato da una delle intermedie bloccate, e controllare che crypto/x509 restituisca errore.

package main

import (
	"crypto/x509"
	"encoding/pem"
	"fmt"
	"os"
)

func main() {
	certPEM, err := os.ReadFile(os.Args[1])
	if err != nil {
 fmt.Println("errore lettura file:", err)
 os.Exit(1)
	}
	block, _ := pem.Decode(certPEM)
	if block == nil {
 fmt.Println("PEM non valido")
 os.Exit(1)
	}
	cert, err := x509.ParseCertificate(block.Bytes)
	if err != nil {
 fmt.Println("errore parsing certificato:", err)
 os.Exit(1)
	}

	roots, _ := x509.SystemCertPool()
	opts := x509.VerifyOptions{Roots: roots}
	if _, err := cert.Verify(opts); err != nil {
 fmt.Println("verifica fallita (atteso se è una delle intermedie bloccate):", err)
 os.Exit(0)
	}
	fmt.Println("ATTENZIONE: verifica riuscita, il certificato è stato accettato")
	os.Exit(2)
}

Compilato con go build -o test-emudhra test.go dopo l'aggiornamento a 1.27.3/1.26.10, e lanciato contro un certificato di test che chiude la catena su una delle otto intermedie bloccate, deve stampare l'errore di verifica e uscire con codice 0. Se il programma stampa "ATTENZIONE" ed esce con codice 2, il binario non è stato ricompilato con il toolchain giusto, oppure il certificato di test non è davvero firmato da una delle chiavi incriminate.

Un dettaglio operativo: per ottenere certificati di test firmati dalle chiavi compromesse serve affidarsi ai pacchetti di test pubblicati dai singoli progetti (per esempio Atlantis ha incluso nel changelog della versione 0.48.2 la spiegazione del cambiamento, utile come riferimento per capire cosa aspettarsi dal comportamento post-patch) piuttosto che generarli da soli: non è lo scopo di questa guida fornire chiavi private compromesse, per ovvie ragioni.

5. Caso NGINX/reverse proxy Go: la dipendenza vendorizzata nascosta

Chi usa un reverse proxy scritto in Go (non NGINX in sé, che è C e non è toccato da questo bug, ma strumenti come Caddy, Traefik o proxy interni custom) deve controllare non solo il binario principale, ma le dipendenze vendorizzate che gestiscono TLS per conto proprio. Il comando utile:

go version -m /usr/local/bin/nome-proxy | grep -i x509

Se il proxy usa una libreria TLS alternativa che non passa da crypto/x509 dello stdlib (capita con alcuni client gRPC o librerie di terze parti che vendorizzano la propria implementazione), il blocco delle intermedie eMudhra non si applica automaticamente: va verificato caso per caso leggendo il go.mod del progetto e cercando dipendenze che importano crypto/x509 con una versione fissata diversa da quella del modulo principale:

go list -m all | grep crypto

Per NGINX puro, il problema si sposta sul trust store di sistema (pacchetto ca-certificates), che è un intervento diverso e non Go-specifico: non rientra in questa guida, ma va comunque verificato separatamente se NGINX fa da client TLS verso backend esterni.

Riepilogo comandi

Cosa fare Comando Ambiente verificato
Controllare versione Go di sistema go version Ubuntu 24.04
Controllare versione Go di un binario go version -m <binario> Ubuntu 24.04
Installare Go via snap sudo snap install go --classic snap, canale latest/stable, verificato 2 novembre 2026 a 1.27.3
Installare Go via tarball tar -C /usr/local -xzf go1.27.3.linux-amd64.tar.gz go.dev/dl, verificato 2 novembre 2026
Scansione di un binario govulncheck -mode=binary <binario> comando indicato dal Go Security team

L'ultimo comando della tabella richiede prima l'installazione di govulncheck con il toolchain corretto pinnato, come indicato dal blog ufficiale Go: GOTOOLCHAIN=go1.27.3+auto go install golang.org/x/vuln/cmd/govulncheck@latest, seguito da govulncheck -mode=binary <path_al_binario>.

Testo redatto con il supporto dell'intelligenza artificiale e verificato dalla redazione (AI Act, art. 50).