caCertsConfig.ts
utils/caCertsConfig.ts
No strong subsystem tag
89
Lines
3608
Bytes
1
Exports
3
Imports
10
Keywords
What this is
This page documents one file from the repository and includes its full source so you can read it without leaving the docs site.
Beginner explanation
This file is one piece of the larger system. Its name, directory, imports, and exports show where it fits. Start by reading the exports and related files first.
How it is used
Start from the exports list and related files. Those are the easiest clues for where this file fits into the system.
Expert explanation
Architecturally, this file intersects with general runtime concerns. It contains 89 lines, 3 detected imports, and 1 detected exports.
Important relationships
Detected exports
applyExtraCACertsFromConfig
Keywords
settingsnode_extra_ca_certsconfigprocessjsonpathonlylogfordebuggingclaudecerts
Detected imports
./config.js./debug.js./settings/settings.js
Source notes
This page embeds the full file contents. Small or leaf files are still indexed honestly instead of being over-explained.
Full source
/**
* Config/settings-backed NODE_EXTRA_CA_CERTS population for `caCerts.ts`.
*
* Split from `caCerts.ts` because `config.ts` → `file.ts` →
* `permissions/filesystem.ts` → `commands.ts` transitively pulls in ~5300
* modules (REPL, React, every slash command). `proxy.ts`/`mtls.ts` (and
* therefore anything using HTTPS through our proxy agent — WebSocketTransport,
* CCRClient, telemetry) must NOT depend on that graph, or the Agent SDK
* bundle (`connectRemoteControl` path) bloats from ~0.4 MB to ~10.8 MB.
*
* `getCACertificates()` only reads `process.env.NODE_EXTRA_CA_CERTS`. This
* module is the one place allowed to import `config.ts` to *populate* that
* env var at CLI startup. Only `init.ts` imports this file.
*/
import { getGlobalConfig } from './config.js'
import { logForDebugging } from './debug.js'
import { getSettingsForSource } from './settings/settings.js'
/**
* Apply NODE_EXTRA_CA_CERTS from settings.json to process.env early in init,
* BEFORE any TLS connections are made.
*
* Bun caches the TLS certificate store at process boot via BoringSSL.
* If NODE_EXTRA_CA_CERTS isn't set in the environment at boot, Bun won't
* include the custom CA cert. By setting it on process.env before any
* TLS connections, we give Bun a chance to pick it up (if the cert store
* is lazy-initialized) and ensure Node.js compatibility.
*
* This is safe to call before the trust dialog because we only read from
* user-controlled files (~/.claude/settings.json and ~/.claude.json),
* not from project-level settings.
*/
export function applyExtraCACertsFromConfig(): void {
if (process.env.NODE_EXTRA_CA_CERTS) {
return // Already set in environment, nothing to do
}
const configPath = getExtraCertsPathFromConfig()
if (configPath) {
process.env.NODE_EXTRA_CA_CERTS = configPath
logForDebugging(
`CA certs: Applied NODE_EXTRA_CA_CERTS from config to process.env: ${configPath}`,
)
}
}
/**
* Read NODE_EXTRA_CA_CERTS from settings/config as a fallback.
*
* NODE_EXTRA_CA_CERTS is categorized as a non-safe env var (it allows
* trusting attacker-controlled servers), so it's only applied to process.env
* after the trust dialog. But we need the CA cert early to establish the TLS
* connection to an HTTPS proxy during init().
*
* We read from global config (~/.claude.json) and user settings
* (~/.claude/settings.json). These are user-controlled files that don't
* require trust approval.
*/
function getExtraCertsPathFromConfig(): string | undefined {
try {
const globalConfig = getGlobalConfig()
const globalEnv = globalConfig?.env
// Only read from user-controlled settings (~/.claude/settings.json),
// not project-level settings, to prevent malicious projects from
// injecting CA certs before the trust dialog.
const settings = getSettingsForSource('userSettings')
const settingsEnv = settings?.env
logForDebugging(
`CA certs: Config fallback - globalEnv keys: ${globalEnv ? Object.keys(globalEnv).join(',') : 'none'}, settingsEnv keys: ${settingsEnv ? Object.keys(settingsEnv).join(',') : 'none'}`,
)
// Settings override global config (same precedence as applyConfigEnvironmentVariables)
const path =
settingsEnv?.NODE_EXTRA_CA_CERTS || globalEnv?.NODE_EXTRA_CA_CERTS
if (path) {
logForDebugging(
`CA certs: Found NODE_EXTRA_CA_CERTS in config/settings: ${path}`,
)
}
return path
} catch (error) {
logForDebugging(`CA certs: Config fallback failed: ${error}`, {
level: 'error',
})
return undefined
}
}