From 98fcc3756b57fcf9dc2fadc8b9e652561a085183 Mon Sep 17 00:00:00 2001 From: Gaurav Tiwari Date: Thu, 22 Oct 2026 14:19:54 +0100 Subject: [PATCH] Update benchmark runtime certificate trust --- test/bench/java_ca_preparation_test.rb | 37 +++++++ test/bench/java_ca_trust_test.rb | 97 +++++++++++++++++++ .../ca-trust/aaa-certificate-services.pem | 25 +++++ test/fixtures/ca-trust/emsign-ecc-root-g3.pem | 15 +++ tools/README.md | 11 +++ tools/docker/n8n-runners-distroless/mise.toml | 2 +- tools/docker/n8n-runners/mise.toml | 2 +- tools/docker/n8n/mise.toml | 2 +- tools/go/hugo/mise.toml | 2 +- tools/gradle/opentelemetry-java/case.toml | 2 +- tools/maven/spring-ai/case.toml | 2 +- tools/moon/zitadel/mise.toml | 2 +- tools/nx/storybook/mise.toml | 2 +- tools/sbt/lila/case.toml | 2 +- tools/sbt/play/case.toml | 2 +- tools/shared/JavaCaTrust.java | 82 ++++++++++++++++ tools/turbo/n8n/mise.toml | 2 +- 17 files changed, 278 insertions(+), 11 deletions(-) create mode 100644 test/bench/java_ca_preparation_test.rb create mode 100644 test/bench/java_ca_trust_test.rb create mode 100644 test/fixtures/ca-trust/aaa-certificate-services.pem create mode 100644 test/fixtures/ca-trust/emsign-ecc-root-g3.pem create mode 100644 tools/shared/JavaCaTrust.java diff --git a/test/bench/java_ca_preparation_test.rb b/test/bench/java_ca_preparation_test.rb new file mode 100644 index 0000000000..5c74c5c4af --- /dev/null +++ b/test/bench/java_ca_preparation_test.rb @@ -0,0 +1,37 @@ +require_relative "test_helper" + +class JavaCaPreparationTest < Minitest::Test + CASES = %w[gradle/opentelemetry-java maven/spring-ai sbt/play sbt/lila].freeze + + def run_preparation(id, mise_exit: 0) + Dir.mktmpdir("java preparation ") do |directory| + bin = File.join(directory, "bin") + FileUtils.mkdir_p(bin) + File.write(File.join(bin, "mise"), "#!/bin/sh\necho mise-$1 >> \"$LOG\"\nexit #{mise_exit}\n") + File.write(File.join(bin, "java"), "#!/bin/sh\ntest -f \"$1\" && test \"$2\" = --apply || exit 1\necho java >> \"$LOG\"\n") + FileUtils.chmod(0o755, Dir[File.join(bin, "*")]) + log = File.join(directory, "calls") + kase = Bench::Catalog.new(Bench::ROOT).find_case(id) + success = system({"PATH" => "#{bin}:#{ENV.fetch('PATH')}", "JAVA_HOME" => directory, + "TEST_JAVA_HOME" => directory, "BENCH_ROOT" => Bench::ROOT, "LOG" => log}, + "bash", "-c", kase.prepare.first, chdir: directory) + [success, File.readlines(log, chomp: true)] + end + end + + def test_every_java_case_repairs_each_selected_jdk_after_installation + CASES.each do |id| + success, calls = run_preparation(id) + + assert success, id + assert_equal ["mise-trust", "mise-install", *Array.new(id.start_with?("gradle/") ? 2 : 1, "java")], calls, id + end + end + + def test_failed_installation_stops_before_java_store_changes + success, calls = run_preparation(CASES.first, mise_exit: 1) + + refute success + assert_equal ["mise-trust"], calls + end +end diff --git a/test/bench/java_ca_trust_test.rb b/test/bench/java_ca_trust_test.rb new file mode 100644 index 0000000000..3860ddb2be --- /dev/null +++ b/test/bench/java_ca_trust_test.rb @@ -0,0 +1,97 @@ +require "minitest/autorun" +require "digest" +require "fileutils" +require "open3" +require "tmpdir" + +class JavaCaTrustTest < Minitest::Test + ROOT = File.expand_path("../..", __dir__) + HELPER = File.join(ROOT, "tools/shared/JavaCaTrust.java") + + def setup + _output, properties, status = Open3.capture3("java", "-XshowSettings:properties", "-version") + skip "A JDK is required for Java trust-store tests" unless status.success? + version = properties[/^\s*java.specification.version = (.+)$/, 1].to_i + skip "Java 17 or newer is required for Java trust-store tests" if version < 17 + @java_home = properties[/^\s*java.home = (.+)$/, 1]&.strip + skip "Could not locate the JDK trust store" unless @java_home + @java = File.join(@java_home, "bin/java") + @keytool = File.join(@java_home, "bin/keytool") + rescue Errno::ENOENT + skip "A JDK is required for Java trust-store tests" + end + + def with_store + Dir.mktmpdir("java-ca-trust") do |directory| + store = File.join(directory, "cacerts") + FileUtils.cp(File.join(@java_home, "lib/security/cacerts"), store) + File.chmod(0o644, store) + yield store + end + end + + def fingerprints(store) + output, error, status = Open3.capture3(@keytool, "-J-Duser.language=en", "-list", "-rfc", "-keystore", store, "-storepass", "changeit") + assert status.success?, error + output.split("Alias name: ").drop(1).to_h do |entry| + alias_name = entry.lines.first.strip + certificate = entry[/-----BEGIN CERTIFICATE-----(.*?)-----END CERTIFICATE-----/m, 1].unpack1("m") + [alias_name, Digest::SHA256.hexdigest(certificate)] + end + end + + def test_repair_preserves_other_roots_permissions_and_original_backup_and_is_idempotent + with_store do |store| + baseline = fingerprints(store) + %w[emsign-ecc-root-g3.pem aaa-certificate-services.pem].each_with_index do |fixture, index| + _output, error, status = Open3.capture3(@keytool, "-importcert", "-noprompt", "-alias", "affected-#{index}", + "-keystore", store, "-storepass", "changeit", "-file", File.join(ROOT, "test/fixtures/ca-trust", fixture)) + assert status.success?, error + end + original = File.binread(store) + _output, error, status = Open3.capture3(@java, HELPER, "--store", store) + refute status.success? + assert_includes error, "affected root certificates" + assert_equal original, File.binread(store) + + output, error, status = Open3.capture3(@java, HELPER, "--store", store, "--apply") + assert status.success?, error + assert_includes output, "Removed" + expected = baseline.reject { |_alias_name, fingerprint| %w[86a1ecba089c4a8d3bbe2734c612ba341d813e043cf9e8a862cd5c57a36bbe6b d7a7a0fb5d7e2731d771e9484ebcdef71d5f0c3e0a2948782bc83ee0ea699ef4].include?(fingerprint) } + assert_equal expected, fingerprints(store) + assert_equal original, File.binread("#{store}.before-emudhra-20261021") + assert_equal 0o644, File.stat(store).mode & 0o777 + + repaired = File.binread(store) + _output, error, status = Open3.capture3(@java, HELPER, "--store", store, "--apply") + assert status.success?, error + assert_equal repaired, File.binread(store) + end + end + + def test_invalid_store_is_not_modified + with_store do |store| + File.binwrite(store, "invalid keystore") + _output, _error, status = Open3.capture3(@java, HELPER, "--store", store, "--apply") + refute status.success? + assert_equal "invalid keystore", File.binread(store) + refute File.exist?("#{store}.before-emudhra-20261021") + end + end + + def test_existing_backup_is_not_overwritten + with_store do |store| + _output, error, status = Open3.capture3(@keytool, "-importcert", "-noprompt", "-alias", "affected", + "-keystore", store, "-storepass", "changeit", "-file", File.join(ROOT, "test/fixtures/ca-trust/emsign-ecc-root-g3.pem")) + assert status.success?, error + original = File.binread(store) + backup = "#{store}.before-emudhra-20261021" + File.binwrite(backup, "earlier backup") + _output, _error, status = Open3.capture3(@java, HELPER, "--store", store, "--apply") + refute status.success? + assert_equal original, File.binread(store) + assert_equal "earlier backup", File.binread(backup) + assert_empty Dir[File.join(File.dirname(store), "cacerts-emudhra-*.tmp")] + end + end +end diff --git a/test/fixtures/ca-trust/aaa-certificate-services.pem b/test/fixtures/ca-trust/aaa-certificate-services.pem new file mode 100644 index 0000000000..33c71ba9db --- /dev/null +++ b/test/fixtures/ca-trust/aaa-certificate-services.pem @@ -0,0 +1,25 @@ +-----BEGIN CERTIFICATE----- +MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb +MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow +GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj +YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL +MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE +BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM +GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua +BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe +3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4 +YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR +rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm +ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU +oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF +MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v +QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t +b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF +AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q +GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz +Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2 +G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi +l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3 +smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== +-----END CERTIFICATE----- diff --git a/test/fixtures/ca-trust/emsign-ecc-root-g3.pem b/test/fixtures/ca-trust/emsign-ecc-root-g3.pem new file mode 100644 index 0000000000..060e943bf7 --- /dev/null +++ b/test/fixtures/ca-trust/emsign-ecc-root-g3.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICTjCCAdOgAwIBAgIKPPYHqWhwDtqLhDAKBggqhkjOPQQDAzBrMQswCQYDVQQG +EwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNo +bm9sb2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0g +RzMwHhcNMTgwMjE4MTgzMDAwWhcNNDMwMjE4MTgzMDAwWjBrMQswCQYDVQQGEwJJ +TjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9s +b2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0gRzMw +djAQBgcqhkjOPQIBBgUrgQQAIgNiAAQjpQy4LRL1KPOxst3iAhKAnjlfSU2fySU0 +WXTsuwYc58Byr+iuL+FBVIcUqEqy6HyC5ltqtdyzdc6LBtCGI79G1Y4PPwT01xyS +fvalY8L1X44uT6EYGQIrMgqCZH0Wk9GjQjBAMB0GA1UdDgQWBBR8XQKEE9TMipuB +zhccLikenEhjQjAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggq +hkjOPQQDAwNpADBmAjEAvvNhzwIQHWSVB7gYboiFBS+DCBeQyh+KTOgNG3qxrdWB +CUfvO6wIBHxcmbHtRwfSAjEAnbpV/KlK6O3t5nYBQnvI+GDZjVGLVTv7jHvrZQnD ++JbNR6iC8hZVdyR+EhCVBCyj +-----END CERTIFICATE----- diff --git a/tools/README.md b/tools/README.md index 8b1522f660..0b7af257fe 100644 --- a/tools/README.md +++ b/tools/README.md @@ -2,6 +2,17 @@ Each directory here is a BoringCache adapter command (`docker`, `cargo`, `turbo`, ...). +Case `mise.toml` files pin Node 22.23.4, 24.22.1 or 26.12.1 and Go 1.27.3, +which include the October 2026 certificate security updates. See the +[Node security release](https://nodejs.org/en/blog/vulnerability/october-2026-security-releases) +and [Go release history](https://go.dev/doc/devel/release). +Java cases run `tools/shared/JavaCaTrust.java --apply` with every selected JDK +after installation and before workload downloads. It removes only the two +reviewed eMudhra root fingerprints, preserves unrelated entries and permissions, +and saves the original store without replacing an existing backup. A repair +failure stops preparation. The same preparation applies to every provider lane. +Earlier result records retain their original harness and toolchain selection. + ``` tools// tool.toml display name and levels: the capability sets lanes implement diff --git a/tools/docker/n8n-runners-distroless/mise.toml b/tools/docker/n8n-runners-distroless/mise.toml index 25f0fa4967..f31abf0407 100644 --- a/tools/docker/n8n-runners-distroless/mise.toml +++ b/tools/docker/n8n-runners-distroless/mise.toml @@ -1,3 +1,3 @@ [tools] -node = "26.7.0" +node = "26.12.1" pnpm = "12.4.2" diff --git a/tools/docker/n8n-runners/mise.toml b/tools/docker/n8n-runners/mise.toml index 25f0fa4967..f31abf0407 100644 --- a/tools/docker/n8n-runners/mise.toml +++ b/tools/docker/n8n-runners/mise.toml @@ -1,3 +1,3 @@ [tools] -node = "26.7.0" +node = "26.12.1" pnpm = "12.4.2" diff --git a/tools/docker/n8n/mise.toml b/tools/docker/n8n/mise.toml index 25f0fa4967..f31abf0407 100644 --- a/tools/docker/n8n/mise.toml +++ b/tools/docker/n8n/mise.toml @@ -1,3 +1,3 @@ [tools] -node = "26.7.0" +node = "26.12.1" pnpm = "12.4.2" diff --git a/tools/go/hugo/mise.toml b/tools/go/hugo/mise.toml index 432e2c8824..89f58b05af 100644 --- a/tools/go/hugo/mise.toml +++ b/tools/go/hugo/mise.toml @@ -1,5 +1,5 @@ [tools] -go = "1.27.1" +go = "1.27.3" [settings] go_set_gobin = false diff --git a/tools/gradle/opentelemetry-java/case.toml b/tools/gradle/opentelemetry-java/case.toml index 484947c967..fc31634a06 100644 --- a/tools/gradle/opentelemetry-java/case.toml +++ b/tools/gradle/opentelemetry-java/case.toml @@ -2,7 +2,7 @@ repo = "open-telemetry/opentelemetry-java" branch = "main" start_sha = "bace7e2236b29c8a9da2cbd4b4d069e690a502dd" directory = "upstream" -prepare = ["mise trust && mise install"] +prepare = ["mise trust && mise install && \"$JAVA_HOME/bin/java\" \"$BENCH_ROOT/tools/shared/JavaCaTrust.java\" --apply && \"$TEST_JAVA_HOME/bin/java\" \"$BENCH_ROOT/tools/shared/JavaCaTrust.java\" --apply"] check = "test -s \"$(find upstream/sdk/all/build/libs -maxdepth 1 -type f -name 'opentelemetry-sdk-*.jar' -print -quit)\"" shared = [".gradle-user-home/caches/modules-2", ".gradle-user-home/wrapper/dists"] diff --git a/tools/maven/spring-ai/case.toml b/tools/maven/spring-ai/case.toml index 6fed4e5a4f..2c93fe2311 100644 --- a/tools/maven/spring-ai/case.toml +++ b/tools/maven/spring-ai/case.toml @@ -2,7 +2,7 @@ repo = "spring-projects/spring-ai" branch = "main" start_sha = "c9dde9c58bac76efd20eef2f344c24a43787c7b2" directory = "upstream" -prepare = ["mise trust && mise install"] +prepare = ["mise trust && mise install && \"$JAVA_HOME/bin/java\" \"$BENCH_ROOT/tools/shared/JavaCaTrust.java\" --apply"] check = "test -s \"$(find upstream/spring-ai-commons/target -maxdepth 1 -type f -name 'spring-ai-commons-*.jar' -print -quit)\"" shared = [".m2/repository", ".m2/wrapper/dists"] diff --git a/tools/moon/zitadel/mise.toml b/tools/moon/zitadel/mise.toml index dc7d5bb8ba..b7cb13dea0 100644 --- a/tools/moon/zitadel/mise.toml +++ b/tools/moon/zitadel/mise.toml @@ -1,2 +1,2 @@ [tools] -node = "24.13.0" +node = "24.22.1" diff --git a/tools/nx/storybook/mise.toml b/tools/nx/storybook/mise.toml index 6d03574bbc..b835fd3983 100644 --- a/tools/nx/storybook/mise.toml +++ b/tools/nx/storybook/mise.toml @@ -1,2 +1,2 @@ [tools] -node = "22.22.3" +node = "22.23.4" diff --git a/tools/sbt/lila/case.toml b/tools/sbt/lila/case.toml index e6ba838753..5938e08b83 100644 --- a/tools/sbt/lila/case.toml +++ b/tools/sbt/lila/case.toml @@ -4,7 +4,7 @@ start_sha = "fda690020b843721c3814ee7d3dd2c384cf0147d" rolling_series = 2 directory = "upstream" prepare = [ - "mise trust && mise install", + "mise trust && mise install && \"$JAVA_HOME/bin/java\" \"$BENCH_ROOT/tools/shared/JavaCaTrust.java\" --apply", "printf '\\naddRemoteCachePlugin\\n' >> upstream/project/plugins.sbt", "cd upstream && cp .sbtopts.default .sbtopts && cp conf/application.conf.default conf/application.conf", "cd upstream && TZ=UTC git log -1 --date=iso-strict-local --pretty='format:app.version.commit = \"%H\"%napp.version.date = \"%ad\"' > conf/version.conf", diff --git a/tools/sbt/play/case.toml b/tools/sbt/play/case.toml index 46ac153804..ff632995b7 100644 --- a/tools/sbt/play/case.toml +++ b/tools/sbt/play/case.toml @@ -4,7 +4,7 @@ start_sha = "07e5d2357243fc9d5362a71e8c8fa73d13f21f5b" rolling_series = 2 directory = "upstream" prepare = [ - "mise trust && mise install", + "mise trust && mise install && \"$JAVA_HOME/bin/java\" \"$BENCH_ROOT/tools/shared/JavaCaTrust.java\" --apply", "git -C upstream fetch --quiet --unshallow --tags origin", "printf '\\naddRemoteCachePlugin\\n' >> upstream/project/plugins.sbt", "cp overlay/version.sbt upstream/version.sbt", diff --git a/tools/shared/JavaCaTrust.java b/tools/shared/JavaCaTrust.java new file mode 100644 index 0000000000..eecbc2bbb7 --- /dev/null +++ b/tools/shared/JavaCaTrust.java @@ -0,0 +1,82 @@ +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; +import java.security.KeyStore; +import java.security.MessageDigest; +import java.util.HashMap; +import java.util.HexFormat; +import java.util.Map; +import java.util.Set; + +public class JavaCaTrust { + private static final Set DISTRUSTED_ROOTS = Set.of( + "86a1ecba089c4a8d3bbe2734c612ba341d813e043cf9e8a862cd5c57a36bbe6b", + "d7a7a0fb5d7e2731d771e9484ebcdef71d5f0c3e0a2948782bc83ee0ea699ef4" + ); + private static final char[] STORE_PASSWORD = "changeit".toCharArray(); + + public static void main(String[] args) throws Exception { + boolean apply = false; + Path store = Path.of(System.getProperty("java.home"), "lib", "security", "cacerts"); + for (int index = 0; index < args.length; index++) { + if (args[index].equals("--apply")) { + apply = true; + } else if (args[index].equals("--store") && index + 1 < args.length) { + store = Path.of(args[++index]); + } else { + throw new IllegalArgumentException("Usage: JavaCaTrust.java [--apply] [--store PATH]"); + } + } + store = store.toRealPath(); + byte[] original = Files.readAllBytes(store); + KeyStore certificates = KeyStore.getInstance(store.toFile(), STORE_PASSWORD); + Map before = fingerprints(certificates); + Map expected = new HashMap<>(before); + expected.entrySet().removeIf(entry -> DISTRUSTED_ROOTS.contains(entry.getValue())); + int removed = before.size() - expected.size(); + if (removed == 0) { + System.out.println("Java trust store rejects the two affected root fingerprints."); + return; + } + if (!apply) { + throw new IllegalStateException("Java trust store contains " + removed + " affected root certificates."); + } + for (String alias : before.keySet()) { + if (!expected.containsKey(alias)) certificates.deleteEntry(alias); + } + Path candidate = Files.createTempFile(store.getParent(), "cacerts-emudhra-", ".tmp"); + try { + Files.copy(store, candidate, StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.COPY_ATTRIBUTES); + try (var output = Files.newOutputStream(candidate)) { + certificates.store(output, STORE_PASSWORD); + } + if (!fingerprints(KeyStore.getInstance(candidate.toFile(), STORE_PASSWORD)).equals(expected)) { + throw new IllegalStateException("Candidate changed unrelated trust entries; original store is unchanged."); + } + if (!MessageDigest.isEqual(original, Files.readAllBytes(store))) { + throw new IllegalStateException("Trust store changed concurrently; candidate was not applied."); + } + Path backup = store.resolveSibling(store.getFileName() + ".before-emudhra-20261021"); + Files.copy(store, backup, StandardCopyOption.COPY_ATTRIBUTES); + Files.move(candidate, store, StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING); + System.out.println("Removed " + removed + " affected Java root certificates; backup: " + backup); + } finally { + Files.deleteIfExists(candidate); + } + } + + private static Map fingerprints(KeyStore store) throws Exception { + Map result = new HashMap<>(); + var aliases = store.aliases(); + while (aliases.hasMoreElements()) { + String alias = aliases.nextElement(); + if (!store.isCertificateEntry(alias)) { + throw new IllegalStateException("Refusing a store containing non-certificate entries."); + } + byte[] encoded = store.getCertificate(alias).getEncoded(); + result.put(alias, HexFormat.of().formatHex(MessageDigest.getInstance("SHA-256").digest(encoded))); + } + if (result.isEmpty()) throw new IllegalStateException("Refusing an empty trust store."); + return result; + } +} diff --git a/tools/turbo/n8n/mise.toml b/tools/turbo/n8n/mise.toml index 9845899752..f31abf0407 100644 --- a/tools/turbo/n8n/mise.toml +++ b/tools/turbo/n8n/mise.toml @@ -1,3 +1,3 @@ [tools] -node = "26.5.1" +node = "26.12.1" pnpm = "12.4.2"