From 38233b61c2a96c6b646ca9b38148bf38a3b537a7 Mon Sep 17 00:00:00 2001 From: HexLab <8422520+HexLab98@users.noreply.github.com> Date: Sat, 18 Jul 2026 05:55:34 +0700 Subject: [PATCH] fix(desktop): trust Windows system CAs for remote gateways (#66304) * fix(desktop): trust Windows system CAs for remote gateways Load Windows-trusted roots into Node's default TLS context before Desktop probes remote backends, while preserving bundled and extra CAs. * test(desktop): cover Windows system CA installation Verify existing trust roots survive the merge and that unsupported or unavailable stores fail open without changing TLS defaults. --- apps/desktop/electron/main.ts | 12 +++ .../electron/windows-system-ca.test.ts | 96 +++++++++++++++++++ apps/desktop/electron/windows-system-ca.ts | 56 +++++++++++ 3 files changed, 164 insertions(+) create mode 100644 apps/desktop/electron/windows-system-ca.test.ts create mode 100644 apps/desktop/electron/windows-system-ca.ts diff --git a/apps/desktop/electron/main.ts b/apps/desktop/electron/main.ts index 750fa1148..692862356 100644 --- a/apps/desktop/electron/main.ts +++ b/apps/desktop/electron/main.ts @@ -5,6 +5,7 @@ import http from 'node:http' import https from 'node:https' import os from 'node:os' import path from 'node:path' +import tls from 'node:tls' import { pathToFileURL } from 'node:url' import { @@ -142,6 +143,7 @@ import { getVenvSitePackagesEntries, resolveVenvHermesCommand } from './windows-hermes-path' +import { installWindowsSystemCaTrust } from './windows-system-ca' import { readWindowsUserEnvVar } from './windows-user-env' import { isPackagedInstallPath as isPackagedInstallPathUnderRoots } from './workspace-cwd' import { readWslWindowsClipboardImage } from './wsl-clipboard-image' @@ -9154,6 +9156,16 @@ app.on('open-url', (event, url) => { }) app.whenReady().then(() => { + const systemCa = installWindowsSystemCaTrust(tls) + + if (systemCa.applied) { + rememberLog( + `[tls] trusting ${systemCa.systemCertificateCount} Windows system CA certificate(s) for backend connections` + ) + } else if (systemCa.error) { + rememberLog(`[tls] could not load Windows system CA certificates: ${systemCa.error}`) + } + if (IS_MAC) { Menu.setApplicationMenu(buildApplicationMenu()) } else { diff --git a/apps/desktop/electron/windows-system-ca.test.ts b/apps/desktop/electron/windows-system-ca.test.ts new file mode 100644 index 000000000..d7e408bd2 --- /dev/null +++ b/apps/desktop/electron/windows-system-ca.test.ts @@ -0,0 +1,96 @@ +import assert from 'node:assert/strict' + +import { test } from 'vitest' + +import { installWindowsSystemCaTrust, type NodeTlsCaApi } from './windows-system-ca' + +function fakeTlsApi( + defaults: string[] = ['bundled-ca', 'extra-ca'], + system: string[] = ['windows-root-ca'] +): NodeTlsCaApi & { installed: string[][] } { + const installed: string[][] = [] + + return { + installed, + getCACertificates(type = 'default') { + return type === 'system' ? [...system] : [...defaults] + }, + setDefaultCACertificates(certificates) { + installed.push([...certificates]) + } + } +} + +test('installs Windows system CAs without dropping existing defaults', () => { + const tlsApi = fakeTlsApi(['mozilla-root', 'extra-ca'], ['machine-root', 'user-root']) + + const result = installWindowsSystemCaTrust(tlsApi, 'win32') + + assert.deepEqual(tlsApi.installed, [['mozilla-root', 'extra-ca', 'machine-root', 'user-root']]) + assert.deepEqual(result, { + applied: true, + systemCertificateCount: 2, + totalCertificateCount: 4 + }) +}) + +test('does not inspect or replace CAs outside Windows', () => { + let reads = 0 + + const tlsApi: NodeTlsCaApi = { + getCACertificates() { + reads += 1 + + return [] + }, + setDefaultCACertificates() { + throw new Error('should not install') + } + } + + const result = installWindowsSystemCaTrust(tlsApi, 'darwin') + + assert.equal(reads, 0) + assert.deepEqual(result, { + applied: false, + systemCertificateCount: 0, + totalCertificateCount: 0 + }) +}) + +test('leaves the existing defaults untouched when Windows has no system CAs', () => { + const tlsApi = fakeTlsApi(['mozilla-root'], []) + + const result = installWindowsSystemCaTrust(tlsApi, 'win32') + + assert.deepEqual(tlsApi.installed, []) + assert.deepEqual(result, { + applied: false, + systemCertificateCount: 0, + totalCertificateCount: 1 + }) +}) + +test('fails open when the runtime cannot load the Windows certificate store', () => { + const tlsApi: NodeTlsCaApi = { + getCACertificates(type = 'default') { + if (type === 'system') { + throw new Error('certificate store unavailable') + } + + return ['mozilla-root'] + }, + setDefaultCACertificates() { + throw new Error('should not install') + } + } + + const result = installWindowsSystemCaTrust(tlsApi, 'win32') + + assert.deepEqual(result, { + applied: false, + systemCertificateCount: 0, + totalCertificateCount: 0, + error: 'certificate store unavailable' + }) +}) diff --git a/apps/desktop/electron/windows-system-ca.ts b/apps/desktop/electron/windows-system-ca.ts new file mode 100644 index 000000000..a9b26b311 --- /dev/null +++ b/apps/desktop/electron/windows-system-ca.ts @@ -0,0 +1,56 @@ +interface NodeTlsCaApi { + getCACertificates(type?: 'default' | 'system'): string[] + setDefaultCACertificates(certificates: string[]): void +} + +interface WindowsSystemCaResult { + applied: boolean + systemCertificateCount: number + totalCertificateCount: number + error?: string +} + +function installWindowsSystemCaTrust( + tlsApi: NodeTlsCaApi, + platform = process.platform +): WindowsSystemCaResult { + if (platform !== 'win32') { + return { + applied: false, + systemCertificateCount: 0, + totalCertificateCount: 0 + } + } + + try { + const defaultCertificates = tlsApi.getCACertificates('default') + const systemCertificates = tlsApi.getCACertificates('system') + + if (systemCertificates.length === 0) { + return { + applied: false, + systemCertificateCount: 0, + totalCertificateCount: defaultCertificates.length + } + } + + const certificates = [...defaultCertificates, ...systemCertificates] + tlsApi.setDefaultCACertificates(certificates) + + return { + applied: true, + systemCertificateCount: systemCertificates.length, + totalCertificateCount: certificates.length + } + } catch (error) { + return { + applied: false, + systemCertificateCount: 0, + totalCertificateCount: 0, + error: error instanceof Error ? error.message : String(error) + } + } +} + +export { installWindowsSystemCaTrust } +export type { NodeTlsCaApi, WindowsSystemCaResult }