Skip to content

feat: load OS CA certificates at startup for corporate environments#3283

Merged
jeanfbrito merged 4 commits intodevfrom
feat/system-ca-certificates
Apr 1, 2026
Merged

feat: load OS CA certificates at startup for corporate environments#3283
jeanfbrito merged 4 commits intodevfrom
feat/system-ca-certificates

Conversation

@jeanfbrito
Copy link
Copy Markdown
Member

@jeanfbrito jeanfbrito commented Mar 30, 2026

Summary

  • Loads CA certificates from the OS trust store at startup using Node.js 24's native tls.setDefaultCACertificates() API — zero external dependencies
  • All Node.js HTTPS connections (Outlook sync, version checks, etc.) automatically trust OS-installed certificates
  • Enabled by default, configurable via useSystemCertificates in overridden-settings.json
  • allowInsecureOutlookConnections remains as a last-resort fallback; a warning is logged when both are active
  • Consolidates certificate documentation into a single admin guide

Why now

Electron has always had a split TLS architecture: the Chromium renderer trusts the OS certificate store, but Node.js in the main process uses a hardcoded Mozilla CA bundle — ignoring corporate CAs entirely. This has been a long-standing pain point (electron/electron#11741), and our previous workaround (allowInsecureOutlookConnections from #3191) simply disabled all TLS verification.

Node.js addressed this in two steps:

  • v22.15.0 (April 2025): added tls.getCACertificates('system') to read OS-trusted certificates
  • v24.5.0 (June 2025): added tls.setDefaultCACertificates() to replace the default CA bundle programmatically

Our upgrade to Electron 40 (Node.js 24.11.1) made both APIs available, enabling a proper solution with no third-party dependencies (previously this required packages like win-ca, mac-ca, or system-ca).

How it works

At boot, before any HTTPS connections, the app calls:

const systemCerts = tls.getCACertificates('system');
const bundledCerts = tls.getCACertificates('bundled');
tls.setDefaultCACertificates([...systemCerts, ...bundledCerts]);

This sets the default CA bundle for all TLS contexts that don't specify their own ca option — covering plain axios, custom https.Agent instances (EWS/NTLM), and any future HTTP client code. The bundled Mozilla CAs are preserved alongside system CAs, so nothing that worked before will break.

Test plan

  • yarn build compiles without errors
  • yarn lint passes
  • App starts and logs System CA certificates: loaded N certificates from OS trust store
  • Outlook sync works on a machine with an enterprise CA in the OS trust store (without allowInsecureOutlookConnections)
  • Setting useSystemCertificates: false in overridden-settings.json disables the feature
  • When both allowInsecureOutlookConnections and system CAs are active, a warning is logged

CORE-1363

Summary by CodeRabbit

  • New Features

    • Added automatic loading of OS trust-store CA certificates at startup to recognize corporate and non-default certificates.
    • Introduced configuration options to manage system certificate behavior and enable secure corporate environments.
  • Documentation

    • Added comprehensive guide for configuring certificate handling, including troubleshooting steps for certificate validation errors and startup issues.

Document the overridden-settings.json configuration for bypassing
SSL certificate validation in Outlook calendar sync, covering
file paths per platform, default behavior, and usage scenarios.
Use Node.js 24's native tls.setDefaultCACertificates() to combine
system-trusted and bundled Mozilla CAs at boot time. This allows
all Node.js HTTPS connections (Outlook sync, version checks, etc.)
to trust certificates from the OS trust store without disabling
TLS verification.

Enabled by default, configurable via useSystemCertificates in
overridden-settings.json. The existing allowInsecureOutlookConnections
remains as a last-resort fallback.
Merge the separate outlook-calendar-insecure-connections.md and
system-ca-certificates.md into a unified corporate-certificate-configuration.md
covering both approaches (system CAs and insecure bypass) in one place.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 30, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b6f0b08f-2723-438d-8361-9900c649c315

📥 Commits

Reviewing files that changed from the base of the PR and between 8e9dfa3 and 96fbdca.

📒 Files selected for processing (2)
  • docs/corporate-certificate-configuration.md
  • src/systemCertificates.ts
✅ Files skipped from review due to trivial changes (2)
  • docs/corporate-certificate-configuration.md
  • src/systemCertificates.ts
📜 Recent review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: check (macos-latest)
  • GitHub Check: check (windows-latest)
  • GitHub Check: check (ubuntu-latest)

Walkthrough

Load OS trust-store CA certificates at startup (optional via useSystemCertificates) and merge them with bundled Mozilla CAs for main-process TLS; add allowInsecureOutlookConnections override and warn when insecure Outlook is enabled alongside applied system CAs. New module exposes status and is invoked early in startup.

Changes

Cohort / File(s) Summary
Documentation
docs/corporate-certificate-configuration.md
New documentation describing system CA loading, overridden-settings.json keys (useSystemCertificates, allowInsecureOutlookConnections), OS-specific file locations, troubleshooting, and admin deployment notes.
System Certificate Loading
src/systemCertificates.ts
New module exporting applySystemCertificates() and getSystemCertificateStatus() plus SystemCertificateStatus type; reads overrides, fetches tls.getCACertificates('system'), merges with Node defaults and calls tls.setDefaultCACertificates(), maintains status and error info.
Startup Initialization
src/main.ts
Call to applySystemCertificates() added immediately after setUserDataDirectory() to apply system CA logic before app readiness and further initialization.
Config Normalization & Logging
src/app/main/data.ts
Centralized normalization for allowInsecureOutlookConnections into isInsecureOutlookEnabled; dispatches normalized value and logs a warning if insecure Outlook is enabled while system CAs are applied.

Sequence Diagram(s)

sequenceDiagram
  participant Main as Main (startup)
  participant SysCert as systemCertificates.applySystemCertificates()
  participant NodeTLS as Node TLS (tls.getCACertificates / tls.setDefaultCACertificates)
  participant Data as App Data Dispatcher
  participant Outlook as Outlook Sync

  Main->>SysCert: invoke applySystemCertificates()
  SysCert->>NodeTLS: getCACertificates('system')
  alt system CAs found
    NodeTLS-->>SysCert: list of system CAs
    SysCert->>NodeTLS: setDefaultCACertificates(merged CAs)
    SysCert-->>Main: status { applied: true, certCount }
  else none or disabled
    NodeTLS-->>SysCert: no system CAs / disabled
    SysCert-->>Main: status { applied: false, certCount: 0 }
  end

  Main->>Data: dispatch allowInsecureOutlookConnections (normalized)
  Data-->>Main: if insecure && status.applied -> log warning
  Main->>Outlook: Outlook sync uses Node TLS defaults for connection verification
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

Suggested labels

type: feature

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately captures the main objective: loading OS CA certificates at startup for corporate environments, directly aligning with the primary change across all files.
Linked Issues check ✅ Passed The code changes fully address CORE-1363 by implementing secure OS CA certificate loading at startup as the default solution, replacing reliance on the insecure allowInsecureOutlookConnections bypass while preserving it as a last-resort fallback.
Out of Scope Changes check ✅ Passed All changes are directly scoped to implementing OS CA certificate loading: new systemCertificates module, startup integration in main.ts, configuration in data.ts, and comprehensive admin documentation—no extraneous modifications detected.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/corporate-certificate-configuration.md`:
- Line 72: The sentence is misleading: the loaders in src/systemCertificates.ts
and src/app/main/data.ts look for a settings file placed alongside app.asar
(next to the app bundle), not generically “outside the app bundle” for
system-wide deployment; update the docs line to explicitly say the override file
must be located beside app.asar in the app directory (alongside the app bundle)
so admins know where the loaders (src/systemCertificates.ts and
src/app/main/data.ts) will read it from.

In `@src/systemCertificates.ts`:
- Around line 17-43: readUseSystemCertificatesSetting currently returns based on
the first file that contains useSystemCertificates, which conflicts with
src/app/main/data.ts where overrides are merged as
{...userDataOverriddenSettings, ...appAsarOverriddenSettings} (app.asar wins).
Change readUseSystemCertificatesSetting to read and parse both paths in
locations, merge them with the same precedence (userData first, then appAsar
overrides), then evaluate the resulting merged.useSystemCertificates value
(treating missing or non-false as true) and return that. Update references to
the locations array and the function readUseSystemCertificatesSetting only—no
other behavior changes.
- Around line 64-65: The current code replaces Node's entire CA list by calling
tls.getCACertificates('bundled') and then
tls.setDefaultCACertificates([...systemCerts, ...bundledCerts]); instead call
tls.getCACertificates() with no arguments to retrieve the runtime's actual
default CA list (which includes bundled + NODE_EXTRA_CA_CERTS + system CAs),
merge your systemCerts into that list (deduplicate if needed) and pass the
combined array to tls.setDefaultCACertificates so you preserve existing default
CAs; update references around tls.getCACertificates,
tls.setDefaultCACertificates, and the systemCerts variable accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: fe1c4c27-a151-469b-b93f-b32f6dc55657

📥 Commits

Reviewing files that changed from the base of the PR and between f5be646 and 8e9dfa3.

📒 Files selected for processing (4)
  • docs/corporate-certificate-configuration.md
  • src/app/main/data.ts
  • src/main.ts
  • src/systemCertificates.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: check (windows-latest)
  • GitHub Check: check (ubuntu-latest)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Use TypeScript strict mode enabled in TypeScript configuration
Use React functional components with hooks instead of class components
Follow FSA (Flux Standard Action) pattern for Redux actions
Use camelCase for file names and PascalCase for component file names
All code must pass ESLint and TypeScript checks
Write self-documenting code with clear naming; avoid unnecessary comments except for complex business logic or non-obvious decisions
Use Fuselage components from @rocket.chat/fuselage for all UI work and only create custom components when Fuselage doesn't provide what's needed
Check Theme.d.ts for valid color tokens when using Fuselage components
Use defensive coding with optional chaining and fallbacks for Linux-only APIs (process.getuid(), process.getgid(), process.geteuid(), process.getegid()) to ensure cross-platform compatibility across Windows, macOS, and Linux

Files:

  • src/main.ts
  • src/app/main/data.ts
  • src/systemCertificates.ts
🧠 Learnings (2)
📚 Learning: 2026-03-06T19:31:11.433Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat.Electron PR: 0
File: src/outlookCalendar/AGENTS.md:0-0
Timestamp: 2026-03-06T19:31:11.433Z
Learning: Applies to src/outlookCalendar/**/*(!preload).ts?(x) : Always use the centralized logger from `logger.ts` (outlookLog, outlookDebug, outlookError, outlookWarn, outlookEventDetail) instead of console.log() for Outlook Calendar module logging

Applied to files:

  • src/app/main/data.ts
📚 Learning: 2026-03-06T19:31:11.433Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat.Electron PR: 0
File: src/outlookCalendar/AGENTS.md:0-0
Timestamp: 2026-03-06T19:31:11.433Z
Learning: Applies to src/outlookCalendar/**/preload.ts : Keep preload.ts logging minimal since it cannot access the verbose logging toggle from Redux Store and all logs always appear

Applied to files:

  • src/app/main/data.ts

- Align settings precedence: read both override files and let appAsar
  win, matching the merge order in data.ts
- Use getCACertificates() (no arg) to preserve NODE_EXTRA_CA_CERTS
  alongside system and bundled CAs
- Clarify doc wording for app ASAR override location
@jeanfbrito jeanfbrito merged commit 358c057 into dev Apr 1, 2026
7 checks passed
@jeanfbrito jeanfbrito deleted the feat/system-ca-certificates branch April 1, 2026 17:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant