Skip to content

fix(auth): honor SSL CA env vars across httpx + requests callsites - #14533

Merged
teknium1 merged 1 commit into
NousResearch:mainfrom
0xbyt4:fix/ssl-verify-consistency
Apr 24, 2026
Merged

fix(auth): honor SSL CA env vars across httpx + requests callsites#14533
teknium1 merged 1 commit into
NousResearch:mainfrom
0xbyt4:fix/ssl-verify-consistency

Conversation

@0xbyt4

@0xbyt4 0xbyt4 commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

Summary

Closes two related gaps in Hermes' SSL/TLS handling, both reported on Discord:

  1. macOS Homebrew Python + Nous Portal OAuth: on macOS, Homebrew's OpenSSL cannot locate the system trust store, causing CERTIFICATE_VERIFY_FAILED against valid public certs. Extends the weixin fix (3a0ec1d) pattern to the shared _resolve_verify() helper in hermes_cli/auth.py.

  2. Custom providers with self-signed certs: agent/model_metadata.py's raw requests.get() calls for custom provider /v1/models endpoints accepted no explicit verify= argument, leaving SSL config to requests' implicit env var handling — which reads REQUESTS_CA_BUNDLE only. Users who set SSL_CERT_FILE or HERMES_CA_BUNDLE were silently ignored.

Details

hermes_cli/auth.py

  • Added _default_verify() helper: on darwin, explicitly loads certifi.where() into an ssl.SSLContext; other platforms return True (httpx default, which uses certifi via its own dependency).
  • _resolve_verify() default and missing-CA fallback paths now return _default_verify() instead of raw True.
  • Added REQUESTS_CA_BUNDLE to env var fallback chain — same env var now works for both httpx (_resolve_verify) and requests callsites.
  • effective_insecure short-circuit unchanged.

agent/model_metadata.py

  • Added _resolve_requests_verify() reading HERMES_CA_BUNDLEREQUESTS_CA_BUNDLESSL_CERT_FILE in priority order, falling through to True when none exist.
  • Applied explicit verify=_resolve_requests_verify() to all 6 requests.get() callsites in the module (including the /v1/models fetch at L630 that surfaced the custom-provider report).

Empirical test (behind the change)

Verified against a self-signed HTTPS server that:

  • requests honors REQUESTS_CA_BUNDLE only — ignores SSL_CERT_FILE
  • httpx honors SSL_CERT_FILE only — ignores REQUESTS_CA_BUNDLE

Hermes now honors all three env vars consistently across both libs.

Behavior matrix

Scenario Before After
macOS + no env var `True` (implicit certifi) `SSLContext(cafile=certifi.where())` — explicit
Linux/Windows + no env var `True` `True` — unchanged
`insecure=True` `False` `False` — unchanged
`HERMES_CA_BUNDLE` + valid `SSLContext` `SSLContext` — unchanged
`REQUESTS_CA_BUNDLE` set (httpx paths) ignored `SSLContext`/path — new support
`SSL_CERT_FILE` set (requests paths) ignored path — new support

Never returns `False` from any default path. Only broadens what counts as a valid CA source.

Test plan

  • 18 new unit tests (`tests/agent/test_model_metadata_ssl.py`, `tests/hermes_cli/test_auth_ssl_macos.py`) — env var precedence, platform gating, certifi ImportError fallback
  • Existing `TestResolveVerifyFallback` tests pinned with autouse `sys.platform="linux"` fixture to keep their "returns True" assertions platform-independent
  • Full regression: 4341/4346 tests pass; 5 pre-existing failures unrelated (verified against `main`)
  • AST parse + import smoke check

Related

  • Prior fix for the same family of problems: 3a0ec1d (weixin: macOS certifi fallback for aiohttp)
  • Discord reports triggered this work — @ee.dd can confirm context

- hermes_cli/auth.py: add _default_verify() with macOS Homebrew certifi
  fallback (mirrors weixin 3a0ec1d). Extend env var chain to include
  REQUESTS_CA_BUNDLE so one env var works across httpx + requests paths.
- agent/model_metadata.py: add _resolve_requests_verify() reading
  HERMES_CA_BUNDLE / REQUESTS_CA_BUNDLE / SSL_CERT_FILE in priority
  order. Apply explicit verify= to all 6 requests.get callsites.
- Tests: 18 new unit tests + autouse platform pin on existing
  TestResolveVerifyFallback to keep its "returns True" assertions
  platform-independent.

Empirically verified against self-signed HTTPS server: requests honors
REQUESTS_CA_BUNDLE only; httpx honors SSL_CERT_FILE only. Hermes now
honors all three everywhere.

Triggered by Discord reports — Nous OAuth SSL failure on macOS
Homebrew Python; custom provider self-signed cert ignored despite
REQUESTS_CA_BUNDLE set in env.
@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists area/auth Authentication, OAuth, credential pools comp/cli CLI entry point, hermes_cli/, setup wizard comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint labels Apr 23, 2026
@teknium1
teknium1 merged commit 8aa37a0 into NousResearch:main Apr 24, 2026
5 of 7 checks passed
teknium1 added a commit that referenced this pull request Apr 24, 2026
Follow-up to PR #14533 — applies the same _resolve_requests_verify()
treatment to the one requests.get() site the PR missed (Codex OAuth
chatgpt.com /models probe). Keeps all seven requests.get() callsites
in model_metadata.py consistent so HERMES_CA_BUNDLE / REQUESTS_CA_BUNDLE /
SSL_CERT_FILE are honored everywhere.

Co-authored-by: teknium1 <teknium@hermes-agent>
nekorytaylor666 pushed a commit to nekorytaylor666/hermes-agent that referenced this pull request Apr 24, 2026
…5049)

Follow-up to PR NousResearch#14533 — applies the same _resolve_requests_verify()
treatment to the one requests.get() site the PR missed (Codex OAuth
chatgpt.com /models probe). Keeps all seven requests.get() callsites
in model_metadata.py consistent so HERMES_CA_BUNDLE / REQUESTS_CA_BUNDLE /
SSL_CERT_FILE are honored everywhere.

Co-authored-by: teknium1 <teknium@hermes-agent>
justrhoto pushed a commit to justrhoto/hermes-agent that referenced this pull request Apr 24, 2026
…5049)

Follow-up to PR NousResearch#14533 — applies the same _resolve_requests_verify()
treatment to the one requests.get() site the PR missed (Codex OAuth
chatgpt.com /models probe). Keeps all seven requests.get() callsites
in model_metadata.py consistent so HERMES_CA_BUNDLE / REQUESTS_CA_BUNDLE /
SSL_CERT_FILE are honored everywhere.

Co-authored-by: teknium1 <teknium@hermes-agent>
aj-nt pushed a commit to aj-nt/hermes-agent that referenced this pull request May 1, 2026
…5049)

Follow-up to PR NousResearch#14533 — applies the same _resolve_requests_verify()
treatment to the one requests.get() site the PR missed (Codex OAuth
chatgpt.com /models probe). Keeps all seven requests.get() callsites
in model_metadata.py consistent so HERMES_CA_BUNDLE / REQUESTS_CA_BUNDLE /
SSL_CERT_FILE are honored everywhere.

Co-authored-by: teknium1 <teknium@hermes-agent>
donald131 pushed a commit to donald131/hermes-agent that referenced this pull request May 2, 2026
…5049)

Follow-up to PR NousResearch#14533 — applies the same _resolve_requests_verify()
treatment to the one requests.get() site the PR missed (Codex OAuth
chatgpt.com /models probe). Keeps all seven requests.get() callsites
in model_metadata.py consistent so HERMES_CA_BUNDLE / REQUESTS_CA_BUNDLE /
SSL_CERT_FILE are honored everywhere.

Co-authored-by: teknium1 <teknium@hermes-agent>
02356abc pushed a commit to 02356abc/hermes-agent that referenced this pull request May 14, 2026
…5049)

Follow-up to PR NousResearch#14533 — applies the same _resolve_requests_verify()
treatment to the one requests.get() site the PR missed (Codex OAuth
chatgpt.com /models probe). Keeps all seven requests.get() callsites
in model_metadata.py consistent so HERMES_CA_BUNDLE / REQUESTS_CA_BUNDLE /
SSL_CERT_FILE are honored everywhere.

Co-authored-by: teknium1 <teknium@hermes-agent>
gweeteve pushed a commit to gweeteve/hermes-agent that referenced this pull request Jun 2, 2026
…5049)

Follow-up to PR NousResearch#14533 — applies the same _resolve_requests_verify()
treatment to the one requests.get() site the PR missed (Codex OAuth
chatgpt.com /models probe). Keeps all seven requests.get() callsites
in model_metadata.py consistent so HERMES_CA_BUNDLE / REQUESTS_CA_BUNDLE /
SSL_CERT_FILE are honored everywhere.

Co-authored-by: teknium1 <teknium@hermes-agent>
waefrebeorn pushed a commit to waefrebeorn/slermes that referenced this pull request Jul 2, 2026
…5049)

Follow-up to PR NousResearch#14533 — applies the same _resolve_requests_verify()
treatment to the one requests.get() site the PR missed (Codex OAuth
chatgpt.com /models probe). Keeps all seven requests.get() callsites
in model_metadata.py consistent so HERMES_CA_BUNDLE / REQUESTS_CA_BUNDLE /
SSL_CERT_FILE are honored everywhere.

Co-authored-by: teknium1 <teknium@hermes-agent>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/auth Authentication, OAuth, credential pools comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint comp/cli CLI entry point, hermes_cli/, setup wizard P2 Medium — degraded but workaround exists type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants