Fehlermeldung
curl: (60) SSL certificate problem: self-signed certificate in certificate chain
Auch ausgegeben als
- curl: (60) SSL certificate problem: self signed certificate in certificate chain
- curl: (60) SSL certificate OpenSSL verify result: self-signed certificate in certificate chain (19)
OpenSSL ab 3.0 gibt „self-signed“ aus; OpenSSL 1.1.1 schreibt „self signed“ ohne Bindestrich, deshalb tauchen beide Schreibweisen in Logs und Suchergebnissen auf. Neuere curl-Releases (in unserem Test 8.22.0) formulieren es als „SSL certificate OpenSSL verify result: self-signed certificate in certificate chain (19)“. Schannel-Builds von curl unter Windows melden diesen Fall als „SEC_E_UNTRUSTED_ROOT“.
curl (OpenSSL backend) — CURLE_PEER_FAILED_VERIFICATION, X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN (19)
Was der Fehler bedeutet
curl ist die vom Server gesendete Kette bis zu einem selbstsignierten Root-Zertifikat hinaufgegangen, und dieses Root-Zertifikat steht nicht im CA-Bundle von curl. Anders als bei „unable to get local issuer certificate“ ist die Kette vollständig: curl sieht das Root-Zertifikat, hat nur keinen Grund, ihm zu vertrauen. In der Praxis gehört es fast immer zu einer Firmen-CA oder zu einem Proxy, der TLS abfängt.
Warum der Fehler auftritt
Ein Proxy mit TLS-Inspektion oder ein Virenscanner signiert Verbindungen neu
häufigZscaler, Netskope, Fortinet, Palo Alto und viele Antivirenprodukte terminieren TLS und präsentieren Zertifikate, die von ihrer eigenen Root-CA ausgestellt wurden und die sie samt dieser Root-CA in der Kette senden. Der Browser vertraut diesem Root-Zertifikat über das Betriebssystem, aber curl in WSL, Docker, Git Bash oder einem CI-Runner liest sein eigenes Bundle und lehnt das Root-Zertifikat ab. Als Aussteller des Zertifikats steht dort der Hersteller des Proxys oder deine Firma, nicht die echte CA der Website.
Der Dienst verwendet ein privates Root-Zertifikat und sendet es in der Kette mit
häufigInterne Dienste, Kubernetes-Ingresses und Appliances verwenden oft ein Zertifikat, das von einem firmeneigenen oder selbst erstellten Root-Zertifikat stammt, und nehmen dieses Root-Zertifikat in die ausgelieferte Kette auf. Das Mitsenden macht es nicht vertrauenswürdig: Ein Vertrauensanker muss bereits auf dem Client vorhanden sein.
Das private Root-Zertifikat ist in einem anderen Speicher installiert
gelegentlichDas Root-Zertifikat wurde dem Windows-Zertifikatsspeicher, dem macOS-Schlüsselbund oder den cacerts von Java hinzugefügt, aber dieses curl liest ein OpenSSL-Bundle wie /etc/ssl/certs/ca-certificates.crt oder die Kopie, die mit Git for Windows, Homebrew oder conda ausgeliefert wird.
Der öffentliche Root Store des Clients ist veraltet
seltenSelten sendet ein Server ein neueres öffentliches Root-Zertifikat, das ein alter, nie aktualisierter Client nicht hat. Ein Update des Pakets ca-certificates behebt das; ist das Root-Zertifikat wirklich öffentlich, können andere Rechner die Website problemlos prüfen.
So behebst du den Fehler
- 1.
Herausfinden, wem das Root-Zertifikat gehört
Sieh dir das letzte Zertifikat der Kette an. Nennt das Subject einen Proxy- oder Security-Anbieter oder den Namen deiner Firma, besteht die Lösung darin, diesem Root-Zertifikat auf diesem Rechner zu vertrauen. Ist es ein unerwarteter Name in einem Netzwerk, das du nicht selbst verwaltest, brich ab: Jemand fängt die Verbindung ab.
bash # Print the subject and issuer of every certificate the server (or the proxy) sends openssl s_client -connect api.example.com:443 -servername api.example.com -showcerts </dev/null 2>/dev/null \ | grep -E '^ *[0-9]+ s:|^ *i:' # The last entry has s: == i: — that self-signed root is what curl does not trust. - 2.
Root-Zertifikat der Firma oder des Proxys zum Zertifikatsspeicher des Systems hinzufügen
Besorge das Root-Zertifikat bei deiner IT-Abteilung (oder exportiere es aus dem Trust Store eines verwalteten Rechners) und installiere es in das Bundle des Betriebssystems, das curl verwendet. Container brauchen es schon beim Build; WSL braucht es innerhalb der Linux-Distribution, nicht nur unter Windows.
bash # Debian, Ubuntu, Alpine sudo cp corp-root-ca.pem /usr/local/share/ca-certificates/corp-root-ca.crt sudo update-ca-certificates # RHEL, Fedora, Amazon Linux sudo cp corp-root-ca.pem /etc/pki/ca-trust/source/anchors/ sudo update-ca-trust - 3.
Dem Root-Zertifikat für einen Befehl oder eine Umgebung vertrauen
--cacert und CURL_CA_BUNDLE ersetzen das Standard-Bundle von curl. Kommuniziert derselbe Prozess auch mit öffentlichen Websites, lass sie deshalb auf eine Datei zeigen, die sowohl die öffentlichen Root-Zertifikate als auch das private enthält.
bash curl --cacert corp-root-ca.pem https://api.example.com/ # Keep public roots too: build one bundle with both cat /etc/ssl/certs/ca-certificates.crt corp-root-ca.pem > /opt/certs/bundle.pem export CURL_CA_BUNDLE=/opt/certs/bundle.pem - 4.
Eigener Server: nicht auf das Mitsenden des Root-Zertifikats verlassen
Liefere das Leaf-Zertifikat und die Zwischenzertifikate aus; verteile das private Root-Zertifikat stattdessen per Konfigurationsmanagement an die Clients. Das Root-Zertifikat mitzusenden verschwendet Bytes und macht ein nicht vertrauenswürdiges Root-Zertifikat niemals vertrauenswürdig.
bash # Serve leaf + intermediates only; clients must already have the root cat api.example.com.crt intermediate.crt > fullchain.pem - 5.
Vorübergehende Diagnose: Aussteller bei abgeschalteter Prüfung ansehen
-k schaltet die Zertifikatsprüfung ab, damit die ausführliche Ausgabe Subject und Aussteller zeigen kann, die der Server präsentiert. Verwende es nur, um das Root-Zertifikat zu identifizieren. Bleibt -k in Skripten stehen, kann jeder auf dem Übertragungsweg den Traffic lesen und verändern, einschließlich Tokens und heruntergeladener Installer.
bash # Diagnostic only: shows who issued the certificate even though curl distrusts it curl -sv -k -o /dev/null https://api.example.com/ 2>&1 | grep -E 'subject:|issuer:'
Verwandte Fehler
curl: (60) SSL certificate problem: unable to get local issuer certificatecurl (OpenSSL backend)curl: (60) SSL certificate problem: self-signed certificatecurl (OpenSSL backend)verify error:num=19:self-signed certificate in certificate chainOpenSSL CLI (openssl s_client / openssl verify)self-signed certificate in certificate chainNode.js tls / https / fetch[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self-signed certifi…Python ssl module (OpenSSL)