diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index b54311b385..45c078a2ce 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -144,9 +144,9 @@ junit-v4-13-1 = { module = "junit:junit", version = "4.13.1" }
kms = { module = "software.amazon.awssdk:kms", version = "2.15.28" }
libphonenumber = { module = "com.googlecode.libphonenumber:libphonenumber", version = "8.12.50" }
listenablefuture = { module = "com.google.guava:listenablefuture", version = "9999.0-empty-to-avoid-conflict-with-guava" }
-log4j-1-2-api = { module = "org.apache.logging.log4j:log4j-1.2-api", version = "2.25.4" }
-log4j-api = { module = "org.apache.logging.log4j:log4j-api", version = "2.25.3" }
-log4j-core = { module = "org.apache.logging.log4j:log4j-core", version = "2.25.4" }
+log4j-1-2-api = { module = "org.apache.logging.log4j:log4j-1.2-api", version = "2.26.1" }
+log4j-api = { module = "org.apache.logging.log4j:log4j-api", version = "2.26.1" }
+log4j-core = { module = "org.apache.logging.log4j:log4j-core", version = "2.26.1" }
management-api = { module = "org.glassfish.external:management-api", version = "3.2.1-b001" }
metrics-spi = { module = "software.amazon.awssdk:metrics-spi", version = "2.15.28" }
miglayout-core = { module = "com.miglayout:miglayout-core", version = "4.2" }
diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml
index 5660a74f19..28595df13e 100644
--- a/gradle/verification-metadata.xml
+++ b/gradle/verification-metadata.xml
@@ -92,6 +92,11 @@
+
+
+
+
+
@@ -117,6 +122,11 @@
+
+
+
+
+
@@ -1935,6 +1945,11 @@
+
+
+
+
+
@@ -1954,6 +1969,14 @@
+
+
+
+
+
+
+
+
@@ -1965,6 +1988,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1980,6 +2019,11 @@
+
+
+
+
+
@@ -1999,6 +2043,14 @@
+
+
+
+
+
+
+
+
diff --git a/server/src/main/java/com/mirth/connect/server/launcher/Log4jBootstrap.java b/server/src/main/java/com/mirth/connect/server/launcher/Log4jBootstrap.java
new file mode 100644
index 0000000000..215f588019
--- /dev/null
+++ b/server/src/main/java/com/mirth/connect/server/launcher/Log4jBootstrap.java
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: MPL-2.0
+// SPDX-FileCopyrightText: 2026 Mitch Gaffigan
+
+package com.mirth.connect.server.launcher;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.io.filefilter.WildcardFileFilter;
+
+/** Utility class for bootstrapping Log4j. */
+final class Log4jBootstrap {
+ private static final File LOG4J_LIB_DIR = new File("./server-lib/log4j");
+ private static final String[] JAR_PATTERNS = { "log4j-core-*.jar", "log4j-api-*.jar", "log4j-1.2-api-*.jar" };
+
+ private Log4jBootstrap() {}
+
+ /** Returns the classpath URLs for the Log4j libraries. */
+ static List getClasspathUrls() throws IOException {
+ return getClasspathUrls(LOG4J_LIB_DIR);
+ }
+
+ /** Unit testable version of getClasspathUrls. */
+ static List getClasspathUrls(File log4jLibDir) throws IOException {
+ List log4jClasspathUrls = new ArrayList<>();
+
+ for (String jarPattern : JAR_PATTERNS) {
+ File[] matchingFiles = log4jLibDir.listFiles((FileFilter) new WildcardFileFilter(jarPattern));
+ if (matchingFiles == null || matchingFiles.length != 1) {
+ throw new IOException("Expected exactly one " + jarPattern + " in " + log4jLibDir.getAbsolutePath());
+ }
+ log4jClasspathUrls.add(matchingFiles[0].toURI().toURL());
+ }
+
+ return log4jClasspathUrls;
+ }
+}
\ No newline at end of file
diff --git a/server/src/main/java/com/mirth/connect/server/launcher/MirthLauncher.java b/server/src/main/java/com/mirth/connect/server/launcher/MirthLauncher.java
index cd3d343fd7..33458f2e08 100644
--- a/server/src/main/java/com/mirth/connect/server/launcher/MirthLauncher.java
+++ b/server/src/main/java/com/mirth/connect/server/launcher/MirthLauncher.java
@@ -43,9 +43,6 @@ public class MirthLauncher {
private static final String LOG4J_PROPERTIES_FILE = "./conf/log4j2.properties";
private static final String PROPERTY_APP_DATA_DIR = "dir.appdata";
private static final String PROPERTY_INCLUDE_CUSTOM_LIB = "server.includecustomlib";
- private static final String[] LOG4J_JAR_FILES = { "./server-lib/log4j/log4j-core-2.25.3.jar",
- "./server-lib/log4j/log4j-api-2.25.3.jar",
- "./server-lib/log4j/log4j-1.2-api-2.25.3.jar" };
private static String appDataDir = null;
@@ -58,9 +55,7 @@ public static void main(String[] args) {
List classpathUrls = new ArrayList<>();
// Always add log4j
- for (String log4jJar : LOG4J_JAR_FILES) {
- classpathUrls.add(new File(log4jJar).toURI().toURL());
- }
+ classpathUrls.addAll(Log4jBootstrap.getClasspathUrls());
classpathUrls.addAll(addServerLauncherLibJarsToClasspath());
URLClassLoader mirthLauncherClassLoader = new URLClassLoader(classpathUrls.toArray(new URL[classpathUrls.size()]), Thread.currentThread().getContextClassLoader());
Thread.currentThread().setContextClassLoader(mirthLauncherClassLoader);
diff --git a/server/src/test/java/com/mirth/connect/server/launcher/Log4jBootstrapTest.java b/server/src/test/java/com/mirth/connect/server/launcher/Log4jBootstrapTest.java
new file mode 100644
index 0000000000..1a27103e93
--- /dev/null
+++ b/server/src/test/java/com/mirth/connect/server/launcher/Log4jBootstrapTest.java
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: MPL-2.0
+// SPDX-FileCopyrightText: 2026 Mitch Gaffigan
+
+package com.mirth.connect.server.launcher;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.net.URL;
+import java.nio.file.Files;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Test;
+
+/** Unit tests for {@link Log4jBootstrap}. */
+public class Log4jBootstrapTest {
+
+ /** Tests that {@link Log4jBootstrap#getClasspathUrls(File)} correctly resolves Log4j JARs regardless of version. */
+ @Test
+ public void testGetClasspathUrlsDoesNotDependOnVersions() throws Exception {
+ File log4jLibDir = Files.createTempDirectory("log4j").toFile();
+ log4jLibDir.deleteOnExit();
+
+ for (String name : Arrays.asList("log4j-core-99.0.0.jar", "log4j-api-99.0.0.jar", "log4j-1.2-api-99.0.0.jar")) {
+ File jarFile = new File(log4jLibDir, name);
+ assertTrue(jarFile.createNewFile());
+ jarFile.deleteOnExit();
+ }
+
+ List classpathUrls = Log4jBootstrap.getClasspathUrls(log4jLibDir);
+
+ assertEquals(Arrays.asList(
+ new File(log4jLibDir, "log4j-core-99.0.0.jar").toURI().toURL(),
+ new File(log4jLibDir, "log4j-api-99.0.0.jar").toURI().toURL(),
+ new File(log4jLibDir, "log4j-1.2-api-99.0.0.jar").toURI().toURL()), classpathUrls);
+ }
+}
\ No newline at end of file