WebFetch tool fails with SSL error behind Zscaler/corporate proxy (Bun runtime ignores NODE_EXTRA_CA_CERTS)
Description
The WebFetch tool fails with unable to get local issuer certificate when running behind a corporate SSL inspection proxy (Zscaler). This happens even when NODE_EXTRA_CA_CERTS is correctly configured and the CA certificate bundle is valid.
Environment
- OS: macOS (Darwin 25.3.0, arm64)
- Claude Code version: Latest (standalone Mach-O binary)
- Node.js version: v25.6.1 (system — not used by Claude Code itself)
- Proxy/SSL inspection: Zscaler (corporate SSL interception)
Root Cause Analysis
Through investigation, I found that the claude binary is compiled with the Bun runtime, not standard Node.js. The TLS certificate chain in the binary is:
1. Load bundled Mozilla CAs (from bun-usockets/src/crypto/root_certs.cpp)
2. IF NODE_USE_SYSTEM_CA === "1" → append system keychain certs
3. IF NODE_EXTRA_CA_CERTS is set → append extra certs from file
The WebFetch tool's internal HTTP client (bundled undici) creates its own dispatcher and does not properly inherit the Bun-patched CA store. The WebFetch code logs:
if (process.env.NODE_EXTRA_CA_CERTS)
w("NODE_EXTRA_CA_CERTS detected - Node.js will automatically append to built-in CAs")
But this assumption is incorrect — it's running in Bun, not Node.js. The undici dispatcher bypasses Bun's global TLS context where the extra CAs were appended.
Reproduction Steps
- Be behind a corporate SSL inspection proxy (e.g., Zscaler)
- Set
NODE_EXTRA_CA_CERTSto a valid PEM bundle containing the proxy's root CA - Verify the cert bundle is valid:
openssl s_client -connect www.linkedin.com:443 -CAfile $NODE_EXTRA_CA_CERTS→Verify return code: 0 (ok) - Verify plain Node.js works:
node -e "fetch('https://www.linkedin.com').then(r => console.log(r.status))"→200 - Use the WebFetch tool in Claude Code →
Error: unable to get local issuer certificate
Evidence
| Method | Result |
|--------|--------|
| curl https://www.linkedin.com | 200 OK |
| node -e "https.get(...)" | 200 OK |
| node -e "fetch(...)" | 200 OK |
| openssl s_client -CAfile $NODE_EXTRA_CA_CERTS | Verify return code: 0 |
| WebFetch tool | unable to get local issuer certificate |
| Playwright browser tool | Works (uses Chromium/system keychain) |
Workaround
Setting NODE_USE_SYSTEM_CA=1 in the environment tells Bun to load certificates from the macOS system keychain (where the Zscaler root CA is already installed), bypassing the issue:
export NODE_USE_SYSTEM_CA=1
Suggested Fix
One or more of:
- Document
NODE_USE_SYSTEM_CA=1as the recommended setting for corporate/proxy environments - Set
NODE_USE_SYSTEM_CA=1by default on macOS — the system keychain is the authoritative trust store and users expect it to work - Fix the undici dispatcher in WebFetch to use Bun's patched TLS context (including
NODE_EXTRA_CA_CERTScerts) rather than creating connections with default/bundled CAs only - Pass the CA bundle explicitly to the undici
Agentconnect options whenNODE_EXTRA_CA_CERTSis set, similar to howCLAUDE_CODE_CLIENT_CERT/CLAUDE_CODE_CLIENT_KEYare already handled for mTLS
Related
This likely affects all users behind corporate SSL inspection proxies (Zscaler, Netskope, Palo Alto, etc.) who rely on NODE_EXTRA_CA_CERTS.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗