Jeder Modellaufruf schlägt nach v0.22.6 fehl? Prüf zuerst den SSL_CERT_FILE-Pfad

Dein Firmennetz läuft über einen Proxy, der HTTPS aufbricht und hineinschaut. Das hast du vor Monaten gelöst: die Firmen-Root als Bundle exportiert, export SSL_CERT_FILE=/etc/corp/ca-bundle.pem, und curl, pip und git verhalten sich normal. Dann aktualisierst du Hermes, schickst eine Nachricht und siehst zu, wie sie hängt – certificate is not trusted im Log, drei Retries und ein trockenes „Provider temporarily unavailable“.
Dein Netz ist nicht kaputt und deine Proxy-Einstellungen sind nicht falsch. Seit v0.22.6 löst der Modell-Client Zertifikatsvertrauen über einen neuen Pfad auf, und das in SSL_CERT_FILE genannte Bundle ist dabei nicht mitgekommen.
Zuerst: prüfen, ob es dieses Problem ist
Die Symptome sind ziemlich eindeutig:
- Jeder provider scheitert, nicht nur einer, und ein Modellwechsel ändert nichts.
- Die Fehlerkette ist
httpcore.ConnectError→httpx.ConnectError→openai.APIConnectionError: Connection error., dazwischen"[host] certificate is not trusted". curloderopenssl s_clienterreichen denselben Host problemlos, weil sieSSL_CERT_FILElesen.- Ein Downgrade derselben Maschine auf v0.22.5 stellt den Normalbetrieb wieder her.
Vier von vier heißt: Zertifikatsvertrauen, nicht Netzpolitik.
Was sich im Code geändert hat
In agent/ssl_verify.py, hinzugefügt in v0.22.6, beantwortet resolve_httpx_verify() die Frage, gegen welches Vertrauen dieser HTTP-Client prüfen soll. Die Reihenfolge ist: Verifikation explizit aus → ein explizites ssl_ca_cert-Bundle → der Plattform-Store. Das Problem sitzt kurz vor diesem letzten Schritt:
if os.environ.get("SSL_CERT_FILE") or os.environ.get("SSL_CERT_DIR"):
return _shared_context(None)
_shared_context(None) heißt „nur der Plattform-Store, kein zusätzliches CA bundle“. Wer SSL_CERT_FILE exportiert, landet also in einem Zweig, der es ignoriert.
Der Docstring des Moduls beschreibt den umgekehrten Vertrag: einem exportierten SSL_CERT_FILE-Bundle wird zusätzlich zu dem Plattform-Store vertraut, und nur explizite Konfiguration pro provider (ssl_ca_cert, ssl_verify: false) ersetzt dieses Vertrauen. platform_ssl_context() in derselben Datei setzt genau diese Vereinigung um. Der Zweig für die Umgebungsvariable und der Rest des Moduls widersprechen sich.
Warum Linux unauffällig wirkte, ist der interessante Teil: das OpenSSL-Backend von truststore ruft set_default_verify_paths() auf, und OpenSSL liest SSL_CERT_FILE selbst – das Vertrauen kam also zufällig an. macOS prüft über SecTrustSetAnchorCertificates, Windows über CryptoAPI; keins von beiden fragt OpenSSLs Umgebung, also scheitern beide hart. Deshalb bricht dieselbe Firmenkonfiguration den Mac einer Kollegin, während deine Linux-Kiste weiterläuft.
Drei Wege daran vorbei, nach Vorliebe sortiert
1. Die Root im Vertrauensspeicher des Betriebssystems installieren (was die Docs empfehlen)
Die Sicherheitsdokumentation ist eindeutig: Installiere die Root eines corporate TLS-Proxy über das Verfahren, das in deiner Organisation für den OS-Vertrauensspeicher gilt. Danach spielt SSL_CERT_FILE für provider-Aufrufe keine Rolle mehr. Unter macOS markierst du das Zertifikat im Schlüsselbund als immer vertrauenswürdig; unter Windows importierst du es über certlm.msc in die vertrauenswürdigen Stammzertifizierungsstellen; unter Debian/Ubuntu legst du das pem in /usr/local/share/ca-certificates/ und führst update-ca-certificates aus. Sauberste Option, übersteht Upgrades, braucht Adminrechte.
2. Den provider explizit auf das Bundle zeigen
Wenn du den System-Store nicht anfassen kannst, setz das CA bundle am provider-Eintrag:
providers:
deepseek:
api: https://api.deepseek.com
key_env: DEEPSEEK_API_KEY
ssl_ca_cert: ${env:SSL_CERT_FILE}
ssl_ca_cert ersetzt das Plattform-Vertrauen für Chat, Modell-Metadaten und Katalog-Probes dieses endpoint. Es repariert nur diesen provider, was meistens genau das ist, was du willst; ein falscher Pfad loggt eine Warnung und fällt auf das Plattform-Vertrauen zurück, statt still zu scheitern.
3. Verifikation abschalten (nur lokale Entwicklung)
ssl_verify: false lässt die Aufrufe sofort laufen und öffnet dich jedem Man-in-the-Middle auf dem Weg – hinter einem corporate inspizierenden Proxy heißt das, dem Proxy rundum zu vertrauen. Die Docs nennen es unsicher für nicht vertrauenswürdige Netze und warnen davor, es als dauerhaften Fix für eine fehlende Root zu nehmen. Zum Diagnostizieren, nicht zum Ausliefern.
Wie das behoben wird
Der Fix-PR (#148253) ändert den Zweig so, dass er platform_ssl_context() statt _shared_context(None) zurückgibt, stellt die dokumentierte Vereinigung wieder her und begründet, warum Linux zu funktionieren schien. Mit dem Release v0.22.7 ist er noch offen, der stabile Build, den du heute installierst, verhält sich also wie bisher. Wenn du darauf wartest, ist die Prüfung einfach: ein Release später schaust du nach, ob dieser Zweig in agent/ssl_verify.py platform_ssl_context() zurückgibt.
Eine Gewohnheit, die sich lohnt
Zertifikatsprobleme verkleiden sich als „das Netz ist down“ oder „der provider hat eine Störung“, weil das Oberflächensymptom ein Verbindungsfehler ist. Wenn das nächste Mal alle provider gleichzeitig ausfallen, mach zuerst einen geschichteten Test: curl --cacert "$SSL_CERT_FILE" https://<host>. Klappt das, liegt der Fehler in der Vertrauensauflösung der Anwendung, nicht im Netz – und du hast gerade eine halbe Stunde Packet Captures gespart.
Weiterlesen: lokale Modelle und selbstsignierte Zertifikate, Secrets lokal verschlüsseln, was sonst im v0.22.7-Fenster steckt, installieren und upgraden.