node/test/system-ca
Robo 3b8330deda
crypto: improve system certificate enumeration logic on macOS
1) Fixed macOS default for missing kSecTrustSettingsResult

When kSecTrustSettingsResult is absent from a trust settings dictionary,
Apple specifies kSecTrustSettingsResultTrustRoot as the default value.

Previously, the trust result evaluation (deny check, self-issued check,
TrustAsRoot check) was inside the block that only executed when
kSecTrustSettingsResult was explicitly present. When the key was absent,
the function fell through to return UNSPECIFIED, incorrectly rejecting
self-signed certificates that should have been trusted via the default.

Move the trust result evaluation outside the conditional block so the
default value of kSecTrustSettingsResultTrustRoot flows through the
same code path as explicit values. This aligns with Chromium's
trust_store_mac.cc implementation.

2) Fix CFRelease leak in IsTrustDictionaryTrustedForPolicy: the
CFDictionaryRef returned by SecPolicyCopyProperties(policy_ref)
was not released when the policy OID matched kSecPolicyAppleSSL.

3) Deduplicate certificates: SecItemCopyMatching can return the same
certificate from multiple keychains.

4) Filter expired certificates.

Signed-off-by: deepak1556 <hop2deep@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/62576
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
2026-06-18 00:15:52 +02:00
..
README.md crypto: improve system certificate enumeration logic on macOS 2026-06-18 00:15:52 +02:00
system-ca.status
test-macos-cert-filtering.mjs crypto: improve system certificate enumeration logic on macOS 2026-06-18 00:15:52 +02:00
test-native-intermediate-certs.mjs
test-native-root-certs-env.mjs
test-native-root-certs.mjs test: forbid use of named imports for fixtures 2026-02-22 23:16:09 +01:00
test-set-default-ca-certificates-append-system-ca.mjs test: forbid use of named imports for fixtures 2026-02-22 23:16:09 +01:00
test-set-default-ca-certificates-override-system.mjs
test-set-default-ca-certificates-system-combinations.js
test.cfg.py

system-ca

Tests for --use-system-ca.

On both macOS and Windows interactive dialogs need confirming to add certificates to the OS trust store.

macOS

Adding the certificate

security add-trusted-cert \
  -k /Users/$USER/Library/Keychains/login.keychain-db \
  test/fixtures/keys/fake-startcom-root-cert.pem
security add-certificates \
  -k /Users/$USER/Library/Keychains/login.keychain-db \
  test/fixtures/keys/intermediate-ca.pem
security add-certificates \
  -k /Users/$USER/Library/Keychains/login.keychain-db \
  test/fixtures/keys/non-trusted-intermediate-ca.pem
security add-trusted-cert \
  -k /Users/$USER/Library/Keychains/login.keychain-db \
  test/fixtures/keys/expired-root-cert.pem
# Self-signed cert with trust settings that lack kSecTrustSettingsResult.
security add-trusted-cert \
  -k /Users/$USER/Library/Keychains/login.keychain-db \
  test/fixtures/keys/selfsigned-no-result-root-cert.pem
security trust-settings-export /tmp/node-trust-settings.plist
CERT_SHA1=$(openssl x509 \
  -in test/fixtures/keys/selfsigned-no-result-root-cert.pem \
  -fingerprint -sha1 -noout | sed 's/.*=//;s/://g')
/usr/libexec/PlistBuddy \
  -c "Delete :trustList:${CERT_SHA1}:trustSettings" \
  /tmp/node-trust-settings.plist
/usr/libexec/PlistBuddy \
  -c "Add :trustList:${CERT_SHA1}:trustSettings array" \
  /tmp/node-trust-settings.plist
/usr/libexec/PlistBuddy \
  -c "Add :trustList:${CERT_SHA1}:trustSettings:0 dict" \
  /tmp/node-trust-settings.plist
security trust-settings-import /tmp/node-trust-settings.plist
rm /tmp/node-trust-settings.plist
# Duplicate cert in a second keychain
security create-keychain -p "test" /tmp/node-test-dup.keychain
security add-certificates \
  -k /tmp/node-test-dup.keychain \
  test/fixtures/keys/fake-startcom-root-cert.pem
security list-keychains -d user -s login.keychain-db /tmp/node-test-dup.keychain

Removing the certificate

security delete-certificate -c 'StartCom Certification Authority' \
  -t /Users/$USER/Library/Keychains/login.keychain-db
security delete-certificate -c 'NodeJS-Test-Intermediate-CA' \
  -t /Users/$USER/Library/Keychains/login.keychain-db
security delete-certificate -c 'NodeJS-Non-Trusted-Test-Intermediate-CA' \
  -t /Users/$USER/Library/Keychains/login.keychain-db
security delete-certificate -c 'NodeJS-Test-Expired-Root' \
  -t /Users/$USER/Library/Keychains/login.keychain-db
security delete-certificate -c 'NodeJS-Test-No-Result-Root' \
  -t /Users/$USER/Library/Keychains/login.keychain-db
security list-keychains -d user -s login.keychain-db
security delete-keychain /tmp/node-test-dup.keychain

Windows

Adding the certificate

Powershell:

Import-Certificate -FilePath .\test\fixtures\keys\fake-startcom-root-cert.cer \
  -CertStoreLocation Cert:\CurrentUser\Root
Import-Certificate -FilePath .\test\fixtures\keys\intermediate-ca.pem \
  -CertStoreLocation Cert:\CurrentUser\CA
Import-Certificate -FilePath .\test\fixtures\keys\non-trusted-intermediate-ca.pem \
  -CertStoreLocation Cert:\CurrentUser\CA

Removing the certificate

$thumbprint = (Get-ChildItem -Path Cert:\CurrentUser\Root | \
  Where-Object { $_.Subject -match "StartCom Certification Authority" }).Thumbprint
Remove-Item -Path "Cert:\CurrentUser\Root\$thumbprint"

$thumbprint = (Get-ChildItem -Path Cert:\CurrentUser\CA | \
  Where-Object { $_.Subject -match "NodeJS-Test-Intermediate-CA" }).Thumbprint
Remove-Item -Path "Cert:\CurrentUser\CA\$thumbprint"

$thumbprint = (Get-ChildItem -Path Cert:\CurrentUser\CA | \
  Where-Object { $_.Subject -match "NodeJS-Non-Trusted-Test-Intermediate-CA" }).Thumbprint
Remove-Item -Path "Cert:\CurrentUser\CA\$thumbprint"

Debian/Ubuntu

Adding the certificate

sudo cp test/fixtures/keys/fake-startcom-root-cert.pem \
  /usr/local/share/ca-certificates/fake-startcom-root-cert.crt
sudo cp test/fixtures/keys/intermediate-ca.pem \
  /usr/local/share/ca-certificates/intermediate-ca.crt
sudo cp test/fixtures/keys/non-trusted-intermediate-ca.pem \
  /usr/local/share/ca-certificates/non-trusted-intermediate-ca.crt
sudo update-ca-certificates

Removing the certificate

sudo rm /usr/local/share/ca-certificates/fake-startcom-root-cert.crt \
  /usr/local/share/ca-certificates/intermediate-ca.crt \
  /usr/local/share/ca-certificates/non-trusted-intermediate-ca.crt
sudo update-ca-certificates --fresh

Other Unix-like systems

For other Unix-like systems, consult their manuals, there are usually file-based processes similar to the Debian/Ubuntu one but with different file locations and update commands.