From 62a0f41523d5e1818d76ef3e9b6f4560053f2445 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Wed, 21 Oct 2026 08:27:18 +0200 Subject: [PATCH 1/3] exclude compromised eMudhra certs from CA bundle --- .github/workflows/appimage.yml | 3 + .github/workflows/debian.yml | 2 + .github/workflows/linux-flatpak.yml | 1 + .github/workflows/linux-makepkg.yml | 1 + .github/workflows/mac-dmg-x64.yml | 2 + .github/workflows/mac-dmg.yml | 3 + .github/workflows/win-exe.yml | 3 + dist/common/RemoveDistrustedCaCerts.java | 58 +++++++++++++++++++ dist/linux/appimage/build.sh | 2 + dist/linux/debian/rules | 1 + .../org.cryptomator.Cryptomator.TEMPLATE.yaml | 1 + dist/linux/makepkg/PKGBUILD.template | 2 + dist/mac/dmg/build.sh | 2 + dist/win/build.ps1 | 4 ++ 14 files changed, 85 insertions(+) create mode 100644 dist/common/RemoveDistrustedCaCerts.java diff --git a/.github/workflows/appimage.yml b/.github/workflows/appimage.yml index 344a86e11..ca347b926 100644 --- a/.github/workflows/appimage.yml +++ b/.github/workflows/appimage.yml @@ -46,6 +46,7 @@ on: - '.github/workflows/appimage.yml' - 'dist/linux/appimage/**' - 'dist/linux/common/**' + - 'dist/common/**' - 'dist/linux/resources/**' env: @@ -134,6 +135,8 @@ jobs: --compress zip-0 env: JMOD_PATHS: ${{ steps.jep-493-check.outputs.jmod_paths }} + - name: Remove distrusted CA certificates from runtime + run: ${JAVA_HOME}/bin/java dist/common/RemoveDistrustedCaCerts.java runtime/lib/security/cacerts - name: Run jpackage run: > ${JAVA_HOME}/bin/jpackage diff --git a/.github/workflows/debian.yml b/.github/workflows/debian.yml index f0d76d6e7..78c94c581 100644 --- a/.github/workflows/debian.yml +++ b/.github/workflows/debian.yml @@ -21,6 +21,7 @@ on: - '.github/workflows/debian.yml' - 'dist/linux/debian/**' - 'dist/linux/common/**' + - 'dist/common/**' - 'dist/linux/resources/**' env: @@ -110,6 +111,7 @@ jobs: cp -r target/mods pkgdir cp -r jmods pkgdir cp -r dist/linux/common/ pkgdir + cp dist/common/RemoveDistrustedCaCerts.java pkgdir/common cp target/cryptomator-*.jar pkgdir/mods tar -cJf cryptomator_${{ steps.deb-version.outputs.debVersion }}.orig.tar.xz -C pkgdir . - name: Patch and rename pkgdir diff --git a/.github/workflows/linux-flatpak.yml b/.github/workflows/linux-flatpak.yml index eb8a17978..c1606a735 100644 --- a/.github/workflows/linux-flatpak.yml +++ b/.github/workflows/linux-flatpak.yml @@ -21,6 +21,7 @@ on: - '.github/workflows/linux-flatpak.yml' - 'dist/linux/flatpak/**' - 'dist/linux/common/**' + - 'dist/common/**' - 'dist/linux/resources/**' jobs: diff --git a/.github/workflows/linux-makepkg.yml b/.github/workflows/linux-makepkg.yml index dfb6ff425..44f5d3f10 100644 --- a/.github/workflows/linux-makepkg.yml +++ b/.github/workflows/linux-makepkg.yml @@ -21,6 +21,7 @@ on: - '.github/workflows/linux-makepkg.yml' - 'dist/linux/makepkg/**' - 'dist/linux/common/**' + - 'dist/common/**' - 'dist/linux/resources/**' jobs: diff --git a/.github/workflows/mac-dmg-x64.yml b/.github/workflows/mac-dmg-x64.yml index 96455be3d..146602ade 100644 --- a/.github/workflows/mac-dmg-x64.yml +++ b/.github/workflows/mac-dmg-x64.yml @@ -137,6 +137,8 @@ jobs: --no-man-pages --strip-debug --compress zip-0 + - name: Remove distrusted CA certificates from runtime + run: ${JAVA_HOME}/bin/java dist/common/RemoveDistrustedCaCerts.java runtime/lib/security/cacerts - name: Run jpackage run: > ${JAVA_HOME}/bin/jpackage diff --git a/.github/workflows/mac-dmg.yml b/.github/workflows/mac-dmg.yml index 2e2feafc8..9fc4e633c 100644 --- a/.github/workflows/mac-dmg.yml +++ b/.github/workflows/mac-dmg.yml @@ -51,6 +51,7 @@ on: paths: - '.github/workflows/mac-dmg.yml' - 'dist/mac/**' + - 'dist/common/**' env: JAVA_DIST: 'temurin' @@ -135,6 +136,8 @@ jobs: --no-man-pages --strip-debug --compress zip-0 + - name: Remove distrusted CA certificates from runtime + run: ${JAVA_HOME}/bin/java dist/common/RemoveDistrustedCaCerts.java runtime/lib/security/cacerts - name: Run jpackage run: > ${JAVA_HOME}/bin/jpackage diff --git a/.github/workflows/win-exe.yml b/.github/workflows/win-exe.yml index 4a08409df..2d358fc9e 100644 --- a/.github/workflows/win-exe.yml +++ b/.github/workflows/win-exe.yml @@ -54,6 +54,7 @@ on: paths: - '.github/workflows/win-exe.yml' - 'dist/win/**' + - 'dist/common/**' env: @@ -156,6 +157,8 @@ jobs: --no-man-pages --strip-debug --compress zip-0 + - name: Remove distrusted CA certificates from runtime + run: ${JAVA_HOME}/bin/java dist/common/RemoveDistrustedCaCerts.java runtime/lib/security/cacerts - name: Run jpackage run: > ${JAVA_HOME}/bin/jpackage diff --git a/dist/common/RemoveDistrustedCaCerts.java b/dist/common/RemoveDistrustedCaCerts.java new file mode 100644 index 000000000..f261114fb --- /dev/null +++ b/dist/common/RemoveDistrustedCaCerts.java @@ -0,0 +1,58 @@ +import java.nio.file.Files; +import java.nio.file.Path; +import java.security.KeyStore; +import java.security.MessageDigest; +import java.security.Security; +import java.util.Collections; +import java.util.HexFormat; +import java.util.Map; + +/** + * Removes distrusted root CA certificates from a JDK {@code cacerts} trust store, matching by SHA-256 fingerprint so that vendor-specific alias names don't matter. + *

+ * Run after {@code jlink} and before {@code jpackage} on the runtime image, e.g. {@code $JAVA_HOME/bin/java dist/common/RemoveDistrustedCaCerts.java runtime/lib/security/cacerts}. + * The trust store is written back password-less, as the JDK expects for {@code cacerts}. + */ +public class RemoveDistrustedCaCerts { + + // Roots affected by the eMudhra intermediate CA key compromise (2026-10-17), see https://emudhra.we-have-a-problem.com/roots.json and https://bugzilla.mozilla.org/show_bug.cgi?id=2083449 + private static final Map DISTRUSTED_SHA256 = Map.of( // + "emSign ECC Root CA - G3", "86A1ECBA089C4A8D3BBE2734C612BA341D813E043CF9E8A862CD5C57A36BBE6B", // + "emSign Root TLS CA - G3", "7DD78D5F4F13459A83DFF9ABBBA62EDBAF6F2D102BF257FD712F4D9F2746ED8D", // + "emSign Root CS CA - G3", "F2EDAAFF3D9B701FB4D14C9F285F8C0BAD90FC3BCC1FA07D47F4718EDABA34A5", // + "AAA Certificate Services", "D7A7A0FB5D7E2731D771E9484EBCDEF71D5F0C3E0A2948782BC83EE0EA699EF4" // Sectigo root that cross-signed the compromised intermediates + ); + + public static void main(String[] args) throws Exception { + if (args.length != 1) { + System.err.println("Usage: java RemoveDistrustedCaCerts.java "); + System.exit(2); + } + var cacerts = Path.of(args[0]); + var keyStore = KeyStore.getInstance(cacerts.toFile(), (char[]) null); + var sha256 = MessageDigest.getInstance("SHA-256"); + var hex = HexFormat.of().withUpperCase(); + int removed = 0; + for (var alias : Collections.list(keyStore.aliases())) { + var cert = keyStore.getCertificate(alias); + if (cert == null) { + continue; + } + var fingerprint = hex.formatHex(sha256.digest(cert.getEncoded())); + if (DISTRUSTED_SHA256.containsValue(fingerprint)) { + keyStore.deleteEntry(alias); + removed++; + System.out.println("Removed distrusted CA certificate \"" + alias + "\" (SHA-256: " + fingerprint + ")"); + } + } + if (removed > 0) { + // store without certificate encryption and MAC, i.e. password-less, otherwise the JDK can't read cacerts + Security.setProperty("keystore.pkcs12.certProtectionAlgorithm", "NONE"); + Security.setProperty("keystore.pkcs12.macAlgorithm", "NONE"); + try (var out = Files.newOutputStream(cacerts)) { + keyStore.store(out, null); + } + } + System.out.println("Removed " + removed + " distrusted CA certificate(s) from " + cacerts + ", " + keyStore.size() + " remaining"); + } +} diff --git a/dist/linux/appimage/build.sh b/dist/linux/appimage/build.sh index 6c6cfd595..a3ecea3b3 100755 --- a/dist/linux/appimage/build.sh +++ b/dist/linux/appimage/build.sh @@ -68,6 +68,8 @@ ${JAVA_HOME}/bin/jlink \ --no-man-pages \ --strip-debug \ --compress zip-0 +## remove distrusted CA certificates from runtime +${JAVA_HOME}/bin/java ../../common/RemoveDistrustedCaCerts.java runtime/lib/security/cacerts # create app dir ${JAVA_HOME}/bin/jpackage \ diff --git a/dist/linux/debian/rules b/dist/linux/debian/rules index d2acc4cd4..5080cf1f9 100755 --- a/dist/linux/debian/rules +++ b/dist/linux/debian/rules @@ -34,6 +34,7 @@ override_dh_auto_build: --no-man-pages \ --strip-debug \ --compress zip-0 + $(JAVA_HOME)/bin/java common/RemoveDistrustedCaCerts.java runtime/lib/security/cacerts $(JAVA_HOME)/bin/jpackage \ --type app-image \ --runtime-image runtime \ diff --git a/dist/linux/flatpak/org.cryptomator.Cryptomator.TEMPLATE.yaml b/dist/linux/flatpak/org.cryptomator.Cryptomator.TEMPLATE.yaml index d65f6f1ea..99cb361b9 100644 --- a/dist/linux/flatpak/org.cryptomator.Cryptomator.TEMPLATE.yaml +++ b/dist/linux/flatpak/org.cryptomator.Cryptomator.TEMPLATE.yaml @@ -105,6 +105,7 @@ modules: --no-man-pages --strip-debug --compress=zip-0 + - $JAVA_HOME/bin/java dist/common/RemoveDistrustedCaCerts.java runtime/lib/security/cacerts - $JAVA_HOME/bin/jpackage --type app-image --runtime-image runtime diff --git a/dist/linux/makepkg/PKGBUILD.template b/dist/linux/makepkg/PKGBUILD.template index cad044b1d..c22802260 100644 --- a/dist/linux/makepkg/PKGBUILD.template +++ b/dist/linux/makepkg/PKGBUILD.template @@ -64,6 +64,8 @@ build() { --strip-debug \ --compress=zip-0 + "$JAVA_HOME/bin/java" ../dist/common/RemoveDistrustedCaCerts.java runtime/lib/security/cacerts + ##Note: jpackage does not allow -beta suffixes, have to strip those "$JAVA_HOME/bin/jpackage" \ --type app-image \ diff --git a/dist/mac/dmg/build.sh b/dist/mac/dmg/build.sh index b90d2b033..ffa0068ca 100755 --- a/dist/mac/dmg/build.sh +++ b/dist/mac/dmg/build.sh @@ -91,6 +91,8 @@ ${JAVA_HOME}/bin/jlink \ --no-man-pages \ --strip-debug \ --compress zip-0 +## remove distrusted CA certificates from runtime +${JAVA_HOME}/bin/java ../../common/RemoveDistrustedCaCerts.java runtime/lib/security/cacerts # create app dir ${JAVA_HOME}/bin/jpackage \ diff --git a/dist/win/build.ps1 b/dist/win/build.ps1 index 246360224..96f081970 100644 --- a/dist/win/build.ps1 +++ b/dist/win/build.ps1 @@ -156,6 +156,10 @@ Invoke-CommandWithExitCheck -Command ` "--compress", "zip-0" #do not compress and use msi compression ) +### remove distrusted CA certificates from runtime +Invoke-CommandWithExitCheck -Command ` + "$Env:JAVA_HOME\bin\java" -Arguments @("$buildDir\..\common\RemoveDistrustedCaCerts.java", "runtime\lib\security\cacerts") + $appPath = ".\$AppName" if ($clean -and (Test-Path -Path $appPath)) { Remove-Item -Path $appPath -Force -Recurse From d18673c74fd3546feb6b2dee5570112d52412c1f Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Wed, 21 Oct 2026 08:33:48 +0200 Subject: [PATCH 2/3] bump version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 004b89378..33f8540bb 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.cryptomator cryptomator - 1.19.3 + 1.19.4 Cryptomator Desktop App From 9bf2d9160284f38001fa036134799aaef29e6894 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Wed, 21 Oct 2026 08:54:59 +0200 Subject: [PATCH 3/3] Update metainfo files --- CHANGELOG.md | 5 +++++ dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml | 3 +++ 2 files changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e70629c9b..94e6798c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,11 @@ The changelog starts with version 1.19.0. Changes to prior versions can be found on the [Github release page](https://github.com/cryptomator/cryptomator/releases). +## [1.19.4](https://github.com/cryptomator/cryptomator/releases/1.19.4) - 2026-10-21 +### Security +* Removed compromised eMudhra certs from app internal CA store ([62a0f41](https://github.com/cryptomator/cryptomator/commit/62a0f41523d5e1818d76ef3e9b6f4560053f2445)) + + ## [1.19.3](https://github.com/cryptomator/cryptomator/releases/1.19.3) - 2026-06-29 ### Added * New error dialog if importing a vault fails ([#4243](https://github.com/cryptomator/cryptomator/pull/4243)) diff --git a/dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml b/dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml index c32020758..4f0693ccd 100644 --- a/dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml +++ b/dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml @@ -84,6 +84,9 @@ + + https://github.com/cryptomator/cryptomator/releases/1.19.4 + https://github.com/cryptomator/cryptomator/releases/1.19.3