Message d’erreur
[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate
Également affiché sous la forme
- ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate
Python ajoute l’emplacement dans le code source C, par exemple « (_ssl.c:1082) » ; le numéro change avec la version de Python et n’a aucune valeur pour le diagnostic. urllib enveloppe l’erreur sous la forme « <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] …> », requests et urllib3 sous la forme « Max retries exceeded … (Caused by SSLError(…)) ».
Python ssl module (OpenSSL) — ssl.SSLCertVerificationError, X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY (20)
Ce que cela signifie
Le module ssl de Python a demandé à OpenSSL de vérifier le certificat du serveur, et OpenSSL n’a pas trouvé l’émetteur du dernier certificat de la chaîne parmi les certificats d’AC chargés par ce SSLContext. Le serveur n’est pas forcément mal configuré : souvent, ce Python consulte simplement un autre fichier d’AC (ou un fichier vide) que celui de votre navigateur ou de votre système d’exploitation.
Pourquoi cela se produit
Python de python.org sous macOS sans ses certificats
fréquenteL’installateur macOS de python.org fournit son propre OpenSSL, qui ne lit pas le trousseau macOS. Tant que « Install Certificates.command » n’a pas été exécuté pour cette version de Python, celle-ci n’a aucun certificat d’AC, et chaque requête HTTPS échoue donc de cette façon.
Une AC privée ou un proxy d’inspection TLS
fréquenteLes services de l’entreprise et les proxys d’entreprise utilisent des certificats dont la racine est distribuée aux machines gérées via le magasin du système d’exploitation. L’OpenSSL de Python ne consulte pas le magasin Windows ou macOS, et les conteneurs Linux n’ont pas la racine à moins qu’elle n’y soit ajoutée.
Le serveur n’envoie pas son certificat intermédiaire
fréquenteOpenSSL ne récupère pas les certificats intermédiaires manquants. Si le serveur n’envoie que son certificat feuille, Python échoue, tandis que les navigateurs, qui mettent en cache et téléchargent les certificats intermédiaires, semblent fonctionner normalement.
L’AC a été ajoutée au magasin du système, mais la bibliothèque utilise certifi
occasionnellerequests, httpx, aiohttp, botocore et pip (avec l’ancienne gestion des certificats) vérifient avec le fichier d’AC de certifi, fourni sous forme de paquet Python. Une racine installée avec update-ca-certificates ou dans le trousseau du système d’exploitation leur est invisible.
SSL_CERT_FILE ou SSL_CERT_DIR pointe vers le mauvais emplacement
rareCes variables remplacent les emplacements par défaut d’OpenSSL. Un chemin laissé par un autre outil, ou un fichier d’AC qui ne contient qu’une racine privée, fait échouer les sites publics (ou l’inverse).
Comment corriger l’erreur
- 1.
Builds python.org pour macOS : exécuter Install Certificates.command
Le script installe certifi et le lie comme fichier d’AC de l’OpenSSL de ce Python. Il doit être exécuté de nouveau après l’installation d’une autre version de Python.
bash # macOS, python.org installer: run once per installed Python version "/Applications/Python 3.14/Install Certificates.command" - 2.
Utiliser le magasin de confiance du système d’exploitation avec truststore
truststore fait vérifier ssl.SSLContext par le système d’exploitation (le trousseau sous macOS, le magasin de certificats Windows, le fichier d’AC du système sous Linux) : les racines déployées par votre service informatique fonctionnent donc aussi dans Python. Il couvre également urllib3, requests et pip, qui l’utilise par défaut depuis pip 24.2.
python # pip install truststore==0.10.5 — verify with the OS trust store (Keychain, Windows store, Linux bundle) import truststore truststore.inject_into_ssl() # call once at start-up, before creating connections import urllib.request urllib.request.urlopen("https://api.example.com/") - 3.
Charger l’AC explicitement pour un client
Pour le code qui communique avec un service privé, passez cafile (ou cadata) à ssl.create_default_context(). Le contexte continue de vérifier les noms d’hôte et les dates.
python import ssl, urllib.request ctx = ssl.create_default_context(cafile="/etc/ssl/private-ca/corp-root-ca.pem") urllib.request.urlopen("https://api.example.com/", context=ctx) - 4.
Vérifier et définir le chemin du fichier d’AC par défaut
ssl.get_default_verify_paths() indique le fichier et le répertoire qu’utilise OpenSSL. SSL_CERT_FILE et SSL_CERT_DIR les remplacent pour le processus ; faites-les pointer vers un fichier d’AC qui contient à la fois les racines publiques et votre AC.
bash # Where does this Python look by default? python3 -c "import ssl; print(ssl.get_default_verify_paths())" # Point OpenSSL-based clients at a bundle that includes your CA export SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt - 5.
Propriétaires de serveurs : envoyer la chaîne complète
Si le handshake ne contient qu’un seul certificat et que son émetteur est une AC intermédiaire publique, configurez le serveur avec le fichier de chaîne complète.
bash # Server side: 1 certificate in the handshake = intermediate missing openssl s_client -connect api.example.com:443 -servername api.example.com -showcerts </dev/null 2>/dev/null \ | grep -c 'BEGIN CERTIFICATE'
Erreurs associées
<urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unab…Python urllib.requestMax retries exceeded with url: / (Caused by SSLError(SSLCertVerificationError(1…requests / urllib3 (Python)There was a problem confirming the ssl certificate: [SSL: CERTIFICATE_VERIFY_FA…pip[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self-signed certifi…Python ssl module (OpenSSL)curl: (60) SSL certificate problem: unable to get local issuer certificatecurl (OpenSSL backend)