Repository: electron/electron
Pull request: fix: exception when reading system certificates via nodejs

Backport of #49028

See that PR for details.


Notes: fix crash when reading system certificates via nodejs tls module

Changed files:
filename: patches/node/.patches
patch: @@ -53,3 +53,4 @@ fix_replace_deprecated_setprototype.patch
 fix_redefined_macos_sdk_header_symbols.patch
 src_use_cp_utf8_for_wide_file_names_on_win32.patch
 fix_ensure_traverseparent_bails_on_resource_path_exit.patch
+src_handle_der_decoding_errors_from_system_certificates.patch

filename: patches/node/src_handle_der_decoding_errors_from_system_certificates.patch
patch: @@ -0,0 +1,74 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Joyee Cheung <joyeec9h3@gmail.com>
+Date: Thu, 20 Nov 2025 13:50:28 +0900
+Subject: src: handle DER decoding errors from system certificates
+
+When decoding certificates from the system store, it's not actually
+guaranteed to succeed. In case the system returns a certificate
+that cannot be decoded (might be related to SSL implementation issues),
+skip them.
+
+diff --git a/src/crypto/crypto_context.cc b/src/crypto/crypto_context.cc
+index 0c6b12f8e17b4a7e86ebc836a4e1cc77333f211a..dacf10c3c2e663b03a251c86d69276d0be0dff9d 100644
+--- a/src/crypto/crypto_context.cc
++++ b/src/crypto/crypto_context.cc
+@@ -505,7 +505,11 @@ void ReadMacOSKeychainCertificates(
+   CFRelease(search);
+ 
+   if (ortn) {
+-    fprintf(stderr, "ERROR: SecItemCopyMatching failed %d\n", ortn);
++    per_process::Debug(DebugCategory::CRYPTO,
++                       "Cannot read certificates from system because "
++                       "SecItemCopyMatching failed %d\n",
++                       ortn);
++    return;
+   }
+ 
+   CFIndex count = CFArrayGetCount(curr_anchors);
+@@ -516,7 +520,9 @@ void ReadMacOSKeychainCertificates(
+ 
+     CFDataRef der_data = SecCertificateCopyData(cert_ref);
+     if (!der_data) {
+-      fprintf(stderr, "ERROR: SecCertificateCopyData failed\n");
++      per_process::Debug(DebugCategory::CRYPTO,
++                         "Skipping read of a system certificate "
++                         "because SecCertificateCopyData failed\n");
+       continue;
+     }
+     auto data_buffer_pointer = CFDataGetBytePtr(der_data);
+@@ -524,9 +530,19 @@ void ReadMacOSKeychainCertificates(
+     X509* cert =
+         d2i_X509(nullptr, &data_buffer_pointer, CFDataGetLength(der_data));
+     CFRelease(der_data);
++
++    if (cert == nullptr) {
++      per_process::Debug(DebugCategory::CRYPTO,
++                         "Skipping read of a system certificate "
++                         "because decoding failed\n");
++      continue;
++    }
++
+     bool is_valid = IsCertificateTrustedForPolicy(cert, cert_ref);
+     if (is_valid) {
+       system_root_certificates_X509->emplace_back(cert);
++    } else {
++      X509_free(cert);
+     }
+   }
+   CFRelease(curr_anchors);
+@@ -636,7 +652,14 @@ void GatherCertsForLocation(std::vector<X509*>* vector,
+         reinterpret_cast<const unsigned char*>(cert_from_store->pbCertEncoded);
+     const size_t cert_size = cert_from_store->cbCertEncoded;
+ 
+-    vector->emplace_back(d2i_X509(nullptr, &cert_data, cert_size));
++    X509* x509 = d2i_X509(nullptr, &cert_data, cert_size);
++    if (x509 == nullptr) {
++      per_process::Debug(DebugCategory::CRYPTO,
++                         "Skipping read of a system certificate "
++                         "because decoding failed\n");
++    } else {
++      vector->emplace_back(x509);
++    }
+   }
+ }
+