Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type { ArgsDef, CommandDef } from "citty";

import { hoistGlobalFlags } from "./commands/global-flags";
import { ConfigError } from "./core/errors";
import { trustSystemCa } from "./core/http/system-ca";
import main from "./main";
import { reportError } from "./output/error";
import { findUnknownCommand, resolveBreadcrumb, showUsage, showUsageJson } from "./output/help";
Expand All @@ -12,6 +13,7 @@ const HELP_FLAGS: ReadonlySet<string> = new Set(["--help", "-h"]);
const JSON_HELP_FLAG = "--json";

async function run(): Promise<void> {
trustSystemCa();
const rawArgs = hoistGlobalFlags(process.argv.slice(2));
const wantsJsonHelp = rawArgs.includes(JSON_HELP_FLAG);

Expand Down
3 changes: 2 additions & 1 deletion src/core/http/network-error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ function networkMessage(code: string | null, target: NetworkTarget, fallback: st
if (TLS_ERROR_CODES.has(code)) {
return (
`Could not reach Metabase: TLS error contacting ${target.host} (${code}) — ` +
`the certificate could not be verified, or https:// was used against a plain-HTTP server.`
`the certificate could not be verified, or https:// was used against a plain-HTTP server. ` +
`For a certificate the OS does not trust either, set NODE_EXTRA_CA_CERTS to its CA bundle.`
);
}
const hint = NETWORK_HINTS[code];
Expand Down
19 changes: 19 additions & 0 deletions src/core/http/system-ca.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import tls from "node:tls";

// Node's default trust store is the bundled Mozilla CA list only, so certificates trusted by
// the OS (corporate proxies, local dev CAs like OrbStack's) fail verification unless the user
// remembers NODE_USE_SYSTEM_CA=1. Merging the system store into the defaults gives every TLS
// connection the same trust the OS has. The APIs exist from Node 22.19 / 24.5; older runtimes
// keep the bundled-only behavior.
export function trustSystemCa(): void {
const canReadSystemStore = typeof tls.getCACertificates === "function";
const canReplaceDefaults = typeof tls.setDefaultCACertificates === "function";
if (!canReadSystemStore || !canReplaceDefaults) {
return;
}
const systemCerts = tls.getCACertificates("system");
if (systemCerts.length === 0) {
return;
}
tls.setDefaultCACertificates([...tls.getCACertificates("default"), ...systemCerts]);
}
Loading