source dump of claude code
at main 88 lines 3.6 kB view raw
1/** 2 * Config/settings-backed NODE_EXTRA_CA_CERTS population for `caCerts.ts`. 3 * 4 * Split from `caCerts.ts` because `config.ts` → `file.ts` → 5 * `permissions/filesystem.ts` → `commands.ts` transitively pulls in ~5300 6 * modules (REPL, React, every slash command). `proxy.ts`/`mtls.ts` (and 7 * therefore anything using HTTPS through our proxy agent — WebSocketTransport, 8 * CCRClient, telemetry) must NOT depend on that graph, or the Agent SDK 9 * bundle (`connectRemoteControl` path) bloats from ~0.4 MB to ~10.8 MB. 10 * 11 * `getCACertificates()` only reads `process.env.NODE_EXTRA_CA_CERTS`. This 12 * module is the one place allowed to import `config.ts` to *populate* that 13 * env var at CLI startup. Only `init.ts` imports this file. 14 */ 15 16import { getGlobalConfig } from './config.js' 17import { logForDebugging } from './debug.js' 18import { getSettingsForSource } from './settings/settings.js' 19 20/** 21 * Apply NODE_EXTRA_CA_CERTS from settings.json to process.env early in init, 22 * BEFORE any TLS connections are made. 23 * 24 * Bun caches the TLS certificate store at process boot via BoringSSL. 25 * If NODE_EXTRA_CA_CERTS isn't set in the environment at boot, Bun won't 26 * include the custom CA cert. By setting it on process.env before any 27 * TLS connections, we give Bun a chance to pick it up (if the cert store 28 * is lazy-initialized) and ensure Node.js compatibility. 29 * 30 * This is safe to call before the trust dialog because we only read from 31 * user-controlled files (~/.claude/settings.json and ~/.claude.json), 32 * not from project-level settings. 33 */ 34export function applyExtraCACertsFromConfig(): void { 35 if (process.env.NODE_EXTRA_CA_CERTS) { 36 return // Already set in environment, nothing to do 37 } 38 const configPath = getExtraCertsPathFromConfig() 39 if (configPath) { 40 process.env.NODE_EXTRA_CA_CERTS = configPath 41 logForDebugging( 42 `CA certs: Applied NODE_EXTRA_CA_CERTS from config to process.env: ${configPath}`, 43 ) 44 } 45} 46 47/** 48 * Read NODE_EXTRA_CA_CERTS from settings/config as a fallback. 49 * 50 * NODE_EXTRA_CA_CERTS is categorized as a non-safe env var (it allows 51 * trusting attacker-controlled servers), so it's only applied to process.env 52 * after the trust dialog. But we need the CA cert early to establish the TLS 53 * connection to an HTTPS proxy during init(). 54 * 55 * We read from global config (~/.claude.json) and user settings 56 * (~/.claude/settings.json). These are user-controlled files that don't 57 * require trust approval. 58 */ 59function getExtraCertsPathFromConfig(): string | undefined { 60 try { 61 const globalConfig = getGlobalConfig() 62 const globalEnv = globalConfig?.env 63 // Only read from user-controlled settings (~/.claude/settings.json), 64 // not project-level settings, to prevent malicious projects from 65 // injecting CA certs before the trust dialog. 66 const settings = getSettingsForSource('userSettings') 67 const settingsEnv = settings?.env 68 69 logForDebugging( 70 `CA certs: Config fallback - globalEnv keys: ${globalEnv ? Object.keys(globalEnv).join(',') : 'none'}, settingsEnv keys: ${settingsEnv ? Object.keys(settingsEnv).join(',') : 'none'}`, 71 ) 72 73 // Settings override global config (same precedence as applyConfigEnvironmentVariables) 74 const path = 75 settingsEnv?.NODE_EXTRA_CA_CERTS || globalEnv?.NODE_EXTRA_CA_CERTS 76 if (path) { 77 logForDebugging( 78 `CA certs: Found NODE_EXTRA_CA_CERTS in config/settings: ${path}`, 79 ) 80 } 81 return path 82 } catch (error) { 83 logForDebugging(`CA certs: Config fallback failed: ${error}`, { 84 level: 'error', 85 }) 86 return undefined 87 } 88}