[Bug] Claude in Chrome WebSocket bridge fails behind Zscaler/corporate TLS proxy (unable to get local issuer certificate)
Description
"Claude in Chrome" fails to connect when behind a Zscaler (or similar corporate TLS inspection) proxy. The WebSocket bridge to wss://bridge.claudeusercontent.com fails with unable to get local issuer certificate because the ws npm library used by the Electron app does not pick up the Zscaler root CA.
Disabling Zscaler resolves the issue immediately. The feature works perfectly with Zscaler off.
Environment
- macOS (Darwin 25.3.0)
- Claude Desktop v1.1.4498 (Electron 40.x)
- Zscaler TLS inspection proxy active
- Chrome extension v1.0.57 installed in active profile
Root Cause Analysis
The "Claude in Chrome" feature connects to wss://bridge.claudeusercontent.com/chrome/{userId} via the ws npm package (bh=require("ws") in the bundled index.js). The ws library uses Node.js's TLS stack (OpenSSL), which does not read the macOS system keychain for trusted CAs.
What we tried (none worked):
NODE_EXTRA_CA_CERTSvialaunchctl setenv— Verified the env var is present in the Claude Desktop process (ps ewwconfirms it), but thewsWebSocket library still fails. Electron may initialize Node's TLS context before the env var is read, or it may be sandboxed from it.
- Adding Zscaler root CA to macOS admin-domain trust (
sudo security add-trusted-cert -d -r trustRoot -p ssl -p basic -k /Library/Keychains/System.keychain) — macOSsecurity verify-certpasses, and/usr/bin/curl(SecureTransport) succeeds, but Node.js/OpenSSL within Electron still rejects the cert.
- Zscaler CA already in System keychain with SSL + Basic trust policies in admin domain — still no effect on Electron's Node.js TLS.
What works:
- Disabling Zscaler — bridge connects immediately
/usr/bin/curl(SecureTransport backend) — trusts the keychain, connects fine- "Control Chrome" MCP — works fine because it uses Electron's built-in Node.js for a local MCP server, not a remote WebSocket
Logs
[Claude in Chrome] Connecting to bridge: wss://bridge.claudeusercontent.com/chrome/da6b2600-...
[Claude in Chrome] Bridge WebSocket error after 922ms: unable to get local issuer certificate
[Claude in Chrome] Bridge connection closed (code: 1006, duration: 0ms)
chrome_bridge_connection_failed | error_type: 'websocket_error'
This repeats every ~30 seconds with exponential backoff.
Suggested Fixes
- Honor
NODE_EXTRA_CA_CERTS— Ensure the env var is read and applied to Node's TLS context before any WebSocket connections are made. This is the standard Node.js mechanism for corporate proxy CAs.
- Use Chromium's network stack for the bridge WebSocket instead of Node.js
ws— Chromium's network layer reads the macOS keychain natively and already trusts Zscaler CAs (Chrome browsing works fine behind Zscaler).
- Read macOS keychain CAs at startup — Use
security find-certificate -a -p /Library/Keychains/System.keychainto export trusted CAs and inject them into Node'stls.rootCertificates.
- Add a Desktop setting for custom CA cert path, similar to how VS Code exposes
http.proxyStrictSSLandhttp.certificateAuthority.
Impact
This affects any user running Claude Desktop behind a corporate TLS inspection proxy (Zscaler, Netskope, Symantec, etc.). "Claude in Chrome" is completely non-functional in these environments. "Control Chrome" MCP still works, so users have a partial workaround for basic browser automation, but the full "Claude in Chrome" side-panel experience is broken.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗