From 15931834d5b2af4c391b1f05cc50575f1bed457b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 28 Jan 2026 19:15:41 +0000 Subject: [PATCH 1/4] Initial plan From bcae7f48846d5da1eba5c745ec91ffc3d040f74d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 28 Jan 2026 19:17:21 +0000 Subject: [PATCH 2/4] Update build.ps1 to trim/join IMAGE_REVISION and check for non-empty Co-authored-by: TimHess <3947063+TimHess@users.noreply.github.com> --- build.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.ps1 b/build.ps1 index 4f81839..5a5a509 100755 --- a/build.ps1 +++ b/build.ps1 @@ -112,8 +112,8 @@ try { if (!$Tag) { if ($env:GITHUB_ACTIONS -eq "true") { $ImageNameWithTag = "$DockerOrg/${Name}:$Version" - $Revision = Get-Content (Join-Path $ImageDirectory "metadata" "IMAGE_REVISION") - if ($Revision) { + $Revision = (Get-Content (Join-Path $ImageDirectory "metadata" "IMAGE_REVISION") -ErrorAction SilentlyContinue | ForEach-Object { $_.Trim() }) -join "" + if ($Revision -and $Revision -ne "") { $ImageNameWithTag += "-$Revision" } $AdditionalTags = "$(Get-Content (Join-Path $ImageDirectory "metadata" "ADDITIONAL_TAGS") | ForEach-Object { $_.replace("$Name","$DockerOrg/$Name") })" From 8f883edb76aa78a4858d05cb805507c0d92ddf22 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 28 Jan 2026 19:18:45 +0000 Subject: [PATCH 3/4] Use cryptographic signature verification in SslTrustConfiguration Co-authored-by: TimHess <3947063+TimHess@users.noreply.github.com> --- shared/ssl-config/SslTrustConfiguration.java | 33 ++++++++++++-------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/shared/ssl-config/SslTrustConfiguration.java b/shared/ssl-config/SslTrustConfiguration.java index 73b1e53..9fe76e3 100644 --- a/shared/ssl-config/SslTrustConfiguration.java +++ b/shared/ssl-config/SslTrustConfiguration.java @@ -80,27 +80,34 @@ public void checkServerTrusted(X509Certificate[] chain, String authType) throws logger.debug("Default trust validation failed, checking development certificates..."); for (X509Certificate cert : chain) { X500Principal certSubject = cert.getSubjectX500Principal(); - X500Principal certIssuer = cert.getIssuerX500Principal(); logger.trace("Checking certificate: {}", certSubject); // Check if this certificate matches or is signed by a dev cert for (X509Certificate devCert : devCerts) { - X500Principal devCertSubject = devCert.getSubjectX500Principal(); - X500Principal devCertIssuer = devCert.getIssuerX500Principal(); - - // Check if certificate matches dev cert (same serial/issuer or exact match) - if (cert.getSerialNumber().equals(devCert.getSerialNumber()) || - certIssuer.equals(devCertIssuer) || - cert.equals(devCert)) { - logger.debug("Trusting certificate signed by development CA: {}", certSubject); - return; // Trusted by development CA + // First check for exact match + if (cert.equals(devCert)) { + logger.debug("Trusting certificate (exact match with development cert): {}", certSubject); + return; } - // Check if this certificate's issuer matches a dev cert's subject - // (meaning the dev cert is the CA that signed this cert) - if (certIssuer.equals(devCertSubject)) { + // Then verify cryptographic signature + // Only trust certs signed by dev CAs if the dev cert is actually a CA + try { + // Check if dev cert has CA basic constraints + boolean isCA = devCert.getBasicConstraints() != -1; + if (!isCA) { + logger.trace("Development cert is not a CA, skipping signature verification: {}", devCert.getSubjectX500Principal()); + continue; + } + + // Verify that the cert was signed by the dev cert's private key + cert.verify(devCert.getPublicKey()); logger.debug("Trusting certificate signed by development CA: {}", certSubject); return; // Trusted by development CA + } catch (Exception verifyException) { + // Signature verification failed, continue checking other dev certs + logger.trace("Signature verification failed for cert {} with dev cert {}: {}", + certSubject, devCert.getSubjectX500Principal(), verifyException.getMessage()); } } } From 4814cf747abcb368a64ec0a5d40e793d5102eb79 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 28 Jan 2026 19:21:08 +0000 Subject: [PATCH 4/4] Address code review feedback Co-authored-by: TimHess <3947063+TimHess@users.noreply.github.com> --- build.ps1 | 2 +- shared/ssl-config/SslTrustConfiguration.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.ps1 b/build.ps1 index 5a5a509..5b0bbb1 100755 --- a/build.ps1 +++ b/build.ps1 @@ -116,7 +116,7 @@ try { if ($Revision -and $Revision -ne "") { $ImageNameWithTag += "-$Revision" } - $AdditionalTags = "$(Get-Content (Join-Path $ImageDirectory "metadata" "ADDITIONAL_TAGS") | ForEach-Object { $_.replace("$Name","$DockerOrg/$Name") })" + $AdditionalTags = "$(Get-Content (Join-Path $ImageDirectory "metadata" "ADDITIONAL_TAGS") -ErrorAction SilentlyContinue | ForEach-Object { $_.replace("$Name","$DockerOrg/$Name") })" } else { $ImageNameWithTag = "$DockerOrg/${Name}:dev" diff --git a/shared/ssl-config/SslTrustConfiguration.java b/shared/ssl-config/SslTrustConfiguration.java index 9fe76e3..71c842f 100644 --- a/shared/ssl-config/SslTrustConfiguration.java +++ b/shared/ssl-config/SslTrustConfiguration.java @@ -100,7 +100,7 @@ public void checkServerTrusted(X509Certificate[] chain, String authType) throws continue; } - // Verify that the cert was signed by the dev cert's private key + // Verify that the cert was signed by the dev cert cert.verify(devCert.getPublicKey()); logger.debug("Trusting certificate signed by development CA: {}", certSubject); return; // Trusted by development CA