/** * Scoped TLS relaxation for `--insecure` / `skipSslVerify`. * * WHY THIS EXISTS * Disabling certificate verification used to be done by setting * `NODE_TLS_REJECT_UNAUTHORIZED = '0'` at start-up and leaving it set. That is * process-global and permanent: from the first LLM call onward, EVERY https * connection in the process was unverified — the update check, a git helper, any * later request — not just the endpoint the user opted out for. In the long-lived * `openlore mcp` daemon that meant the rest of the session. * * WHY IT IS DONE THIS WAY * Node's built-in `fetch` accepts no per-request TLS options, and an `Agent` from * the npm `undici` package is rejected by it (`UND_ERR_INVALID_ARG`) because the * built-in fetch is a separate undici instance. Verified on Node 25. So the env var * is still the only lever available without either adding `undici` as a dependency * AND switching these call sites to its `fetch` export, or rewriting them onto * `https.request`. Both are real options; see the note at the bottom. * * What changed is the LIFETIME. The variable is now set immediately before a * request and restored immediately after, which is safe because: * - certificate verification happens during the TLS handshake, inside `fetch()`, * so restoring once `fetch()` resolves does not affect an in-flight body — a * streamed response continues to read fine afterwards, and * - deleting the variable genuinely re-enables verification; Node does not cache * the previous value. * Both behaviours are asserted in `tls-scope.test.ts` rather than assumed. * * REMAINING EXPOSURE, stated plainly: the variable is still process-global while a * scope is open. An unrelated https request that happens to be in flight during * that window is also unverified. The window is now one request rather than the * process lifetime, which is a large reduction but not elimination. Eliminating it * requires per-request TLS options, i.e. one of the two migrations above. * * CHILD PROCESSES were the worst part of that exposure, and are closed. A child * spawned while a scope is open inherits `NODE_TLS_REJECT_UNAUTHORIZED=0` for its * WHOLE LIFETIME — not for one request — so a background index build or a detached * consolidation started in that window ran entirely unverified. Spawn sites pass * `childEnvWithoutScopedTlsRelaxation()` so the child sees the operator's own value * instead of this module's temporary one. */ /** * Record that the user opted out of TLS verification, and say so once. * * This deliberately does NOT disable anything by itself — it only grants * `withRelaxedTls` permission to relax verification around individual requests. * * `announce: false` is for callers that print their own (better) notice — the CLI * renders a colorized one and honours `--quiet`. Without that opt-out this would * both duplicate the message and write to stderr in quiet mode. */ export declare function allowInsecureTls(reason: string, opts?: { announce?: boolean; }): void; /** Announce an instance-scoped TLS opt-out without granting a process-wide capability. */ export declare function announceInsecureTls(reason: string, opts?: { announce?: boolean; }): void; /** * The operator's TLS opt-out, read from the environment. * * WHY AN ENV VAR AT ALL, given `--insecure` already exists: `--insecure` is a CLI * flag, and the paths that most often face an internal self-signed endpoint never * see a command line — the long-lived `openlore mcp` daemon, and the decisions gate * spawned by the git pre-commit hook. Those had NO operator lever for the LLM path; * embeddings had one (`EMBED_SKIP_SSL_VERIFY`) and the LLM did not. * * WHY EVERY KEY IS SURFACE-SCOPED, and there is deliberately NO global one: needing * to relax verification for one surface and not the other is the ordinary case — an * internal self-signed embedding server alongside an LLM vendor with a perfectly * valid certificate. A single switch would force the operator to relax BOTH to fix * one, a strictly larger exposure than the problem requires, and it would be the * broadest ambient lever in the codebase while an `openlore mcp` daemon is running. * The case it would serve — every outbound endpoint behind one internal CA — is * exactly what `NODE_EXTRA_CA_CERTS` handles properly, by making the certificates * VERIFY rather than skipping the check. So two scoped keys, and no union: * * - `EMBED_SKIP_SSL_VERIFY` — embedding requests only * - `LLM_SKIP_SSL_VERIFY` — LLM provider requests only * * The trust boundary is unchanged: this reads the OPERATOR's environment, never the * analyzed repository's `.openlore/config.json` (see `repo-config-trust.ts`). A clone * still cannot disable verification on the machine analyzing it. * * Prefer `NODE_EXTRA_CA_CERTS` over either key wherever the signing CA is available. */ /** Env spelling that relaxes embedding requests only. */ export declare const EMBED_TLS_ENV = "EMBED_SKIP_SSL_VERIFY"; /** Env spelling that relaxes LLM provider requests only. */ export declare const LLM_TLS_ENV = "LLM_SKIP_SSL_VERIFY"; /** True when the operator set `scopeKey` to an affirmative value. */ export declare function envTlsOptOut(scopeKey: string): boolean; /** * Whether verification is relaxed for a surface right now: the operator's scoped env key, * OR the process-wide `--insecure` capability. * * Every relaxable request site MUST go through one of these rather than deciding for itself. * Passing an explicit `false` to `withRelaxedTls` silently opts a site OUT of the CLI flag, * and omitting the argument silently opts it out of the env key — the codebase had one of * each, so `--insecure` did not reach embeddings and `LLM_SKIP_SSL_VERIFY` did not reach the * viewer's chat and model-listing requests. */ export declare function llmTlsRelaxed(): boolean; export declare function embeddingTlsRelaxed(): boolean; /** Whether the user has opted out of certificate verification. */ export declare function isInsecureTlsAllowed(): boolean; /** * Run `fn` with certificate verification relaxed when the caller's own capability * enables it. Callers without an instance capability may inherit the CLI-wide opt-in. * * Wrap the `await fetch(...)` itself — not the surrounding bookkeeping and not the * body read. That is the narrowest span that still covers the handshake. */ export declare function withRelaxedTls(fn: () => Promise, enabled?: boolean): Promise; /** * `base` with this module's TEMPORARY relaxation removed, for handing to a child process. * * The distinction that matters: an operator who exported * `NODE_TLS_REJECT_UNAUTHORIZED` themselves keeps it (that is their machine's * setting, and `savedValue` is exactly it); only the value an open scope wrote is * stripped. With no scope open this returns `base` untouched, so it is safe to call * unconditionally at any spawn site. */ export declare function childEnvWithoutScopedTlsRelaxation(base?: NodeJS.ProcessEnv): NodeJS.ProcessEnv; /** Test-only: clear module state between cases. */ export declare function resetTlsScopeForTests(): void; //# sourceMappingURL=tls-scope.d.ts.map