Commit 71fd9590397 for nodejs

commit 71fd959039790cee7de8ac5752bbf259f07a308d
Author: René <contact.9a5d6388@renegade334.me.uk>
Date:   Fri Nov 13 07:28:41 2026 +0000

    tools: update mk-ca-bundle to 1.35

    Adds the facility to ignore root certificates by fingerprint using
    mk-ca-bundle's -x parameter.

    Signed-off-by: Renegade334 <contact.9a5d6388@renegade334.me.uk>
    PR-URL: https://github.com/nodejs/node/pull/67403
    Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
    Reviewed-By: Ulises Gascón <ulisesgascongonzalez@gmail.com>

diff --git a/tools/dep_updaters/update-root-certs.mjs b/tools/dep_updaters/update-root-certs.mjs
index 80b6fb33f74..a4cdc1be986 100644
--- a/tools/dep_updaters/update-root-certs.mjs
+++ b/tools/dep_updaters/update-root-certs.mjs
@@ -8,6 +8,14 @@ import { pipeline } from 'node:stream/promises';
 import { fileURLToPath } from 'node:url';
 import { parseArgs } from 'node:util';

+// SHA-256 fingerprints of root certificates to exclude from node-root-certs.h
+// Fingerprints can be found in the certificate report at
+// https://ccadb.my.salesforce-sites.com/mozilla/IncludedRootCertificateReport
+const ignoreRoots = [
+  // /* Example Root CA */
+  // '0000000000000000000000000000000000000000000000000000000000000000',
+];
+
 const __filename = fileURLToPath(import.meta.url);

 const getCertdataURL = (version) => {
@@ -145,9 +153,14 @@ if (values.verbose) {
 }
 const opts = { encoding: 'utf8' };
 const mkCABundleTool = join(checkoutDir, 'tools', 'mk-ca-bundle.pl');
-const mkCABundleOut = execFileSync(mkCABundleTool,
-                                   values.verbose ? [ '-v' ] : [],
-                                   opts);
+const mkCABundleArgs = [];
+if (values.verbose) {
+  mkCABundleArgs.push('-v');
+}
+if (ignoreRoots.length) {
+  mkCABundleArgs.push('-x', ignoreRoots.join(','));
+}
+const mkCABundleOut = execFileSync(mkCABundleTool, mkCABundleArgs, opts);
 if (values.verbose) {
   console.log(mkCABundleOut);
 }
diff --git a/tools/mk-ca-bundle.pl b/tools/mk-ca-bundle.pl
index 6763ac52bf2..4911e84d52b 100755
--- a/tools/mk-ca-bundle.pl
+++ b/tools/mk-ca-bundle.pl
@@ -37,14 +37,14 @@ use Getopt::Std;
 use MIME::Base64;
 use strict;
 use warnings;
-use vars qw($opt_h $opt_i $opt_l $opt_m $opt_p $opt_q $opt_s $opt_t $opt_v $opt_w);
+use vars qw($opt_h $opt_i $opt_l $opt_m $opt_p $opt_q $opt_s $opt_t $opt_v $opt_w $opt_x);
 use List::Util;
 use Text::Wrap;

 # If the OpenSSL commandline is not in search path you can configure it here!
 my $openssl = 'openssl';

-my $version = '1.33';
+my $version = '1.35';

 $opt_w = 72; # default base64 encoded lines length

@@ -94,7 +94,7 @@ my @valid_signature_algorithms = (

 $0 =~ s@.*(/|\\)@@;
 $Getopt::Std::STANDARD_HELP_VERSION = 1;
-getopts('hilmp:qs:tvw:');
+getopts('hilmp:qs:tvw:x:');

 if($opt_i) {
     print ("=" x 78 . "\n");
@@ -107,7 +107,7 @@ if($opt_i) {
 }

 sub HELP_MESSAGE() {
-    print "Usage:\t${0} [-i] [-l] [-m] [-p<purposes:levels>] [-q] [-s<algorithms>] [-t] [-v] [-w<l>] [<outputfile>]\n";
+    print "Usage:\t${0} [-i] [-l] [-m] [-p<purposes:levels>] [-q] [-s<algorithms>] [-t] [-v] [-w<l>] [-x<sha256>] [<outputfile>]\n";
     print "\t-i\tprint version info about used modules\n";
     print "\t-l\tprint license info about certdata.txt\n";
     print "\t-m\tinclude meta data in output\n";
@@ -125,6 +125,7 @@ sub HELP_MESSAGE() {
     print "\t-t\tinclude plain text listing of certificates\n";
     print "\t-v\tbe verbose and print out processed CAs\n";
     print "\t-w <l>\twrap base64 output lines after <l> chars (default: ${opt_w})\n";
+    print "\t-x\texclude list of SHA-256 fingerprints. Comma separated, case-insensitive, whitespace and ':' byte delimiters are ignored.\n";
     exit;
 }

@@ -202,9 +203,17 @@ my $txt = dirname(__FILE__) . '/certdata.txt';

 my $stdout = $crt eq '-';

+my @opt_x_list;
+if($opt_x) {
+    $opt_x = uc $opt_x;
+    $opt_x =~ s/[\s:]//g;
+    @opt_x_list = split(/,/, $opt_x);
+}
+
 if($stdout) {
     open(CRT, '> -') or die "Could not open STDOUT: $!\n";
-} else {
+}
+else {
     open(CRT, ">", "$crt.~") or die "Could not open $crt.~: $!\n";
 }

@@ -356,9 +365,11 @@ while(<TXT>) {
             if(/^CKA_TRUST_([A-Z_]+)\s+CK_TRUST\s+CKT_NSS_([A-Z_]+)\s*$/) {
                 if(!is_in_list($1, @valid_mozilla_trust_purposes)) {
                     report "Warning: Unrecognized trust purpose for cert: $caname. Trust purpose: $1. Trust Level: $2";
-                } elsif(!is_in_list($2, @valid_mozilla_trust_levels)) {
+                }
+                elsif(!is_in_list($2, @valid_mozilla_trust_levels)) {
                     report "Warning: Unrecognized trust level for cert: $caname. Trust purpose: $1. Trust Level: $2";
-                } else {
+                }
+                else {
                     push @{$trust_purposes_by_level{$2}}, $1;
                 }
             }
@@ -380,11 +391,23 @@ while(<TXT>) {
         }

         if(!should_output_cert(%trust_purposes_by_level)) {
-            $skipnum ++;
+            $skipnum++;
             report "Skipping: $caname lacks acceptable trust level" if($opt_v);
-        } elsif($caname =~ /TrustCor/) {
-            $skipnum ++;
-        } else {
+        }
+        else {
+            # Skip if explicitly excluded
+            if($opt_x) {
+                my ($fingerprint_sha256) = grep { m{^// Fingerprint .*SHA.*256}i } @precert;
+                $fingerprint_sha256 =~ s/://g;
+                $fingerprint_sha256 = uc $fingerprint_sha256;
+                ($fingerprint_sha256) = $fingerprint_sha256 =~ /([A-F0-9]{64})/;
+                if(grep { $_ eq $fingerprint_sha256 } @opt_x_list) {
+                    report "Skipping: '$main_block_name' fingerprint explicitly excluded: $fingerprint_sha256";
+                    $skipnum++;
+                    next;
+                }
+            }
+
             my $encoded = MIME::Base64::encode_base64($cka_value, '');
             $encoded =~ s/(.{1,${opt_w}})/"$1\\n"\n/g;
             my $pem = "\"-----BEGIN CERTIFICATE-----\\n\"\n"
@@ -402,7 +425,8 @@ while(<TXT>) {
             }
             if(!$opt_t) {
                 print CRT $pem;
-            } else {
+            }
+            else {
                 my $pipe = "";
                 foreach my $hash (@included_signature_algorithms) {
                     $pipe = "|$openssl x509 -" . $hash . " -fingerprint -noout -inform PEM";