[BUG] Native macOS 2.1.292 rejects Telia CA chain; explicit CA bundle fixes TLS
Summary
Claude Code 2.1.292's native macOS arm64 executable fails to verify an HTTPS LLM gateway whose certificate chains to Telia Root CA v2. Node.js and Python verify the same endpoint on the same machine. Setting NODE_EXTRA_CA_CERTS to the existing Homebrew CA bundle makes the same Claude request succeed.
Internal hostnames, credentials, and account details are omitted.
Environment
- Claude Code: 2.1.292, native Mach-O arm64 executable
- macOS 26.7.1, Apple Silicon; zsh
- Comparison runtime: Node.js v22.23.1
- Gateway: LiteLLM 1.103.1, Anthropic Messages API
- Authentication:
apiKeyHelperreturning a bearer token - Corporate HTTPS proxy is configured, with the gateway's hostname suffix in
NO_PROXY. Direct Node/Python requests also succeed. CLAUDE_CODE_CERT_STOREandNODE_EXTRA_CA_CERTSunset in the failing reproduction- TLS verification was never disabled
Certificate chain
The gateway sends a complete three-certificate chain:
- Gateway leaf, issued by Telia Server CA v3 (valid until February 3, 2027)
- Telia Server CA v3, issued by Telia Root CA v2
- Self-signed Telia Root CA v2
The self-signed root is present in macOS's SystemRootCertificates.keychain and the Homebrew CA bundle, with SHA-256 fingerprint:
24:2B:69:74:2F:CB:1E:5B:2A:BF:98:89:8B:94:57:21:87:54:4E:5B:4D:99:11:78:65:73:62:1F:6A:74:B8:2C
System.keychain also contains a cross-signed certificate with the same subject, Telia Root CA v2, issued by TeliaSonera Root CA v1. Whether this affects path selection is unconfirmed.
Reproduction
With ANTHROPIC_BASE_URL and apiKeyHelper already configured for the gateway, run from a directory without project configuration:
env -u NODE_EXTRA_CA_CERTS claude -p "Reply with exactly: ok" \
--model claude-haiku-4.5 \
--tools "" \
--strict-mcp-config \
--mcp-config '{"mcpServers":{}}' \
--no-session-persistence \
--max-turns 1 \
--debug-file /tmp/claude-default-tls.log
Result: exit 1, SSL certificate verification failure.
CA certs: stores=bundled,system, extraCertsPath=undefined
CA certs: Loaded 121 bundled root certificates
CA certs: Dropped 2 expired certificate(s) from system store
CA certs: Loaded 18 system CA certificates
Connection error details: code=UNABLE_TO_GET_ISSUER_CERT (SSL error), message=unable to get issuer certificate
Repeat the same command with an explicit bundle:
NODE_EXTRA_CA_CERTS=/opt/homebrew/etc/openssl@3/cert.pem claude -p "Reply with exactly: ok" \
--model claude-haiku-4.5 \
--tools "" \
--strict-mcp-config \
--mcp-config '{"mcpServers":{}}' \
--no-session-persistence \
--max-turns 1 \
--debug-file /tmp/claude-explicit-tls.log
Result: exit 0, response ok.
CA certs: stores=bundled,system, extraCertsPath=/opt/homebrew/etc/openssl@3/cert.pem
CA certs: Loaded 121 bundled root certificates
CA certs: Dropped 2 expired certificate(s) from system store
CA certs: Loaded 18 system CA certificates
CA certs: Appended extra certificates from NODE_EXTRA_CA_CERTS (/opt/homebrew/etc/openssl@3/cert.pem)
Independent verification
- Python
ssl.create_default_context()verifies the gateway using/opt/homebrew/etc/openssl@3/cert.pem. - Node.js
https.get()verifies it with noNODE_EXTRA_CA_CERTSand returns HTTP 200 from its unauthenticated health endpoint. - Node.js v22.23.1 reports 145 bundled roots, including the self-signed Telia Root CA v2 and TeliaSonera Root CA v1.
- The Homebrew bundle contains 203 certificates, including both roots.
- The failing and successful Claude requests were tested back-to-back, against the same endpoint, with tools/MCP disabled.
Expected behavior
Claude should verify this valid chain using trusted roots available on the machine, or explain which trust source/certificate is missing. The network documentation says the native installer supports reading the OS certificate store.
Investigation limits
The evidence isolates the failure to the native client's trust material or certificate path handling. It does not establish whether the defect is missing bundled roots, system-store enumeration, cross-signed certificate selection, or another TLS path-building behavior. The count of 18 system certificates alone does not prove erroneous enumeration.
Workaround
export NODE_EXTRA_CA_CERTS=/opt/homebrew/etc/openssl@3/cert.pem
Set before starting Claude. This preserves TLS verification and fixes both the isolated reproduction and the interactive session.
Related reports
- #72712: native macOS client loads a small system-certificate set and fails primary API requests
- #74588: native macOS executable TLS failure on an earlier version
- #71766: TLS path-building failures involving cross-signed roots on Linux
This report adds a reproducible gateway/Telia-chain case on 2.1.292 where an existing root CA bundle alone resolves the failure.