Skip to content

Avoid blocking on macOS system certificates - #116

Merged
Christof Marti (chrmarti) merged 7 commits into
mainfrom
chrmarti/macos-system-cert-worker
Sep 2, 2026
Merged

Avoid blocking on macOS system certificates#116
Christof Marti (chrmarti) merged 7 commits into
mainfrom
chrmarti/macos-system-cert-worker

Conversation

@chrmarti

@chrmarti Christof Marti (chrmarti) commented Sep 2, 2026

Copy link
Copy Markdown

Summary

Load Node.js system certificates in a worker on macOS so keychain trust evaluation does not block the extension-host main thread. Start loading when the proxy resolver is created, before the first network request, when Node system certificates and certificate injection are enabled.

This addresses microsoft/vscode#333830.

Session Context

Key decisions from the development session:

  • Worker only on macOS: The multi-second blocking behavior comes from macOS keychain trust evaluation through trustd; Windows and Linux retain their existing loading paths.
  • Preload inside createProxyResolver: Preloading ships atomically with the worker implementation. Adding preload calls directly to VS Code before updating this package would run the old synchronous implementation during startup.
  • Preserve certificate behavior: If worker startup or execution fails, loading falls back to the previous synchronous Node.js API rather than silently dropping system certificates.
  • Retry transient failures: Rejected certificate promises are removed from both caches so one failed preload does not permanently poison later requests.
  • Minor version bump: The package version is incremented from 0.44.0 to 0.45.0.

Changes

  • Run tls.getCACertificates('system') in a worker thread on macOS.
  • Cache Node and legacy system certificate loaders independently.
  • Preload additional certificates during proxy resolver creation when applicable.
  • Add coverage for early preload and retry after loading failures.
  • Update the package and lockfile version to 0.45.0.

Validation

  • npm run compile
  • npm run test:unit — 36 passing
  • Manual runtime check confirmed the loader returns control in approximately 1 ms while the event loop remains responsive; the cached call completes in approximately 0.02 ms.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

A few concrete issues remain around worker lifecycle/logging/test naming (including avoiding eval-based workers where possible) that should be addressed before merge.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review tier: Lite
Findings: 2 Medium severity · 2 Low severity

New issues introduced by this change (4)
Severity Finding
Medium severity src/​index.ts — The worker is created with { eval: true }, which relies on runtime code evaluation. Even though…
Medium severity src/​index.ts — The worker is not unref()'d. If certificate loading stalls (e.g., trustd issues), the worker…
Low severity src/​index.ts — The preload error log label says loadSystemCertificates, but the code is preloading…
Low severity tests/​src/​resolveProxyByURL.test.ts — This test only asserts that loadAdditionalCertificates is invoked during resolver creation; it…
What changed in this PR

This PR updates the certificate-loading path to avoid macOS keychain trust evaluation blocking the main thread by moving Node.js system certificate loading into a worker thread, and it preloads certificate data when a proxy resolver is created.

Changes:

  • Run tls.getCACertificates('system') in a worker thread on macOS and cache system-certificate loads separately by loader type.
  • Start preloading certificate data during createProxyResolver when certificate injection + Node system certificates are enabled.
  • Add/adjust unit tests for preload behavior and cache retry semantics; bump version to 1.0.0 and update changelog.
File Description
src/​index.ts Adds macOS worker-based system certificate loading, preload trigger, and improved cache retry behavior.
tests/​src/​resolveProxyByURL.test.ts Adds a test asserting certificate preload is initiated on macOS.
tests/​src/​certificateLoading.test.ts Adds test coverage for retrying certificate loading after a failure.
package.json Bumps package version to 1.0.0.
package-lock.json Updates lockfile version fields to 1.0.0.
CHANGELOG.md Adds 1.0.0 entry documenting macOS worker-based system cert loading.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/index.ts Outdated
Comment thread src/index.ts Outdated
Comment thread src/index.ts
Comment thread tests/src/resolveProxyByURL.test.ts
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

The system certificate worker does not currently close/terminate after posting its result, which can leave an unnecessary worker thread alive for the lifetime of the process.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review tier: Lite
Findings: 1 Medium severity

New issues introduced by this change (1)
Severity Finding
Medium severity src/​systemCertificatesWorker.ts — The worker posts the certificate list but never closes its message port or terminates, so the…
Issues resolved since last review (4)
Severity Finding
Low severity tests/​src/​resolveProxyByURL.test.ts — This test only asserts that loadAdditionalCertificates is invoked during resolver creation; it… View resolved comment
Low severity src/​index.ts — The preload error log label says loadSystemCertificates, but the code is preloading… View resolved comment
Medium severity src/​index.ts — The worker is not unref()'d. If certificate loading stalls (e.g., trustd issues), the worker… View resolved comment
Medium severity src/​index.ts — The worker is created with { eval: true }, which relies on runtime code evaluation. Even though… View resolved comment

Comment thread src/systemCertificatesWorker.ts
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@chrmarti
Christof Marti (chrmarti) marked this pull request as ready for review September 2, 2026 12:00
@chrmarti
Christof Marti (chrmarti) merged commit dea54fc into main Sep 2, 2026
6 checks passed
@chrmarti
Christof Marti (chrmarti) deleted the chrmarti/macos-system-cert-worker branch September 2, 2026 12:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants