Come appare il messaggio
curl: (60) SSL certificate problem: unable to get local issuer certificateCause frequenti
- Il server invia solo il proprio certificato, non la catena (
cert.peminvece difullchain.pem). - Il bundle CA del client manca o è vecchio (pacchetto
ca-certificates). - Python su macOS senza certificati installati, o un venv con il suo
certifi. - Un proxy aziendale con TLS inspection sostituisce i certificati con una CA interna.
- CA interna o privata installata solo su alcune macchine.
Verifica
- Mostra la catena inviata: subject e issuer di ogni certificato
openssl s_client -connect example.com:443 -servername example.com -showcerts </dev/null 2>/dev/null | grep -E '^ *[0-9] s:|^ *i:' - Mostra i dettagli dell'errore di curl
curl -vI https://example.com 2>&1 | grep -iE 'issuer|verify|SSL certificate' - Mostra i percorsi CA di Python
python3 -c 'import ssl; print(ssl.get_default_verify_paths())' - Verifica che il bundle CA di sistema esista
openssl x509 -in /etc/ssl/certs/ca-certificates.crt -noout -subject 2>/dev/null | head -n 1
Soluzione
- Sul server invia la catena completa: in nginx
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;. - Sul client aggiorna il bundle CA:
apt install --reinstall ca-certificates && update-ca-certificates. - Aggiungi una CA privata al sistema: copiala in
/usr/local/share/ca-certificates/ed eseguiupdate-ca-certificates. - Con TLS inspection aggiungi la CA aziendale al client, ad es. con
REQUESTS_CA_BUNDLEoNODE_EXTRA_CA_CERTS. - Mai usare
curl -koverify=Falsein modo permanente: TLS diventa inutile.
Domande frequenti
Perché nel browser funziona e con curl no?
I browser spesso scaricano da soli gli intermedi mancanti o li hanno in cache. curl e Python no, quindi mostrano il problema reale.
Come riconosco una catena mancante?
openssl s_client -showcerts mostra un solo certificato (0 s:…). Con la catena corretta segue almeno un intermedio (1 s:…).