diff --git a/catalogs/catalog-jdbc-common/src/main/java/org/apache/gravitino/catalog/jdbc/utils/DataSourceUtils.java b/catalogs/catalog-jdbc-common/src/main/java/org/apache/gravitino/catalog/jdbc/utils/DataSourceUtils.java
index 59da59b77..467d19f2d 100644
--- a/catalogs/catalog-jdbc-common/src/main/java/org/apache/gravitino/catalog/jdbc/utils/DataSourceUtils.java
+++ b/catalogs/catalog-jdbc-common/src/main/java/org/apache/gravitino/catalog/jdbc/utils/DataSourceUtils.java
@@ -45,6 +45,22 @@ public class DataSourceUtils {
 
   public static DataSource createDataSource(JdbcConfig jdbcConfig)
       throws GravitinoRuntimeException {
+    // Reject H2 JDBC URLs and driver classes. H2's INIT connection parameter runs arbitrary
+    // SQL when a database is first opened, and via CREATE ALIAS it compiles/runs arbitrary
+    // Java inside the server JVM. An unauthenticated caller can otherwise reach this path
+    // through the catalog testConnection API and achieve remote code execution
+    // (CVE-2026-41042). H2 is only the internal entity-store backend and must never be used
+    // for a user-facing catalog connection.
+    String decodedUrl = recursiveDecode(jdbcConfig.getJdbcUrl().toLowerCase());
+    if (decodedUrl.startsWith("jdbc:h2")) {
+      throw new GravitinoRuntimeException(
+          "H2 JDBC URL is not allowed in catalog configuration");
+    }
+    String jdbcDriver = jdbcConfig.getJdbcDriver();
+    if (jdbcDriver != null && jdbcDriver.toLowerCase().startsWith("org.h2.")) {
+      throw new GravitinoRuntimeException(
+          "H2 JDBC driver is not allowed in catalog configuration");
+    }
     try {
       return createDBCPDataSource(jdbcConfig);
     } catch (Exception exception) {
diff --git a/catalogs/catalog-lakehouse-paimon/src/main/java/org/apache/gravitino/catalog/lakehouse/paimon/utils/CatalogUtils.java b/catalogs/catalog-lakehouse-paimon/src/main/java/org/apache/gravitino/catalog/lakehouse/paimon/utils/CatalogUtils.java
index d479dfa43..98676e972 100644
--- a/catalogs/catalog-lakehouse-paimon/src/main/java/org/apache/gravitino/catalog/lakehouse/paimon/utils/CatalogUtils.java
+++ b/catalogs/catalog-lakehouse-paimon/src/main/java/org/apache/gravitino/catalog/lakehouse/paimon/utils/CatalogUtils.java
@@ -30,6 +30,7 @@ import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.HADOOP_SECURITY
 
 import com.google.common.base.Preconditions;
 import java.io.File;
+import java.net.URLDecoder;
 import java.sql.SQLException;
 import java.util.HashMap;
 import java.util.Map;
@@ -41,6 +42,7 @@ import org.apache.gravitino.catalog.lakehouse.paimon.authentication.Authenticati
 import org.apache.gravitino.catalog.lakehouse.paimon.authentication.kerberos.KerberosClient;
 import org.apache.gravitino.catalog.lakehouse.paimon.ops.PaimonBackendCatalogWrapper;
 import org.apache.gravitino.exceptions.ConnectionFailedException;
+import org.apache.gravitino.exceptions.GravitinoRuntimeException;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.paimon.catalog.Catalog;
 import org.apache.paimon.catalog.CatalogContext;
@@ -138,7 +140,24 @@ public class CatalogUtils {
     }
 
     if (PaimonCatalogBackend.JDBC.name().equalsIgnoreCase(metastore)) {
+      // Reject H2 JDBC URLs and driver classes for the Paimon JDBC metastore backend.
+      // Paimon's own JdbcCatalog opens the connection through DriverManager (not through
+      // DataSourceUtils), so the DataSourceUtils H2 block does not protect this path.
+      // H2's INIT parameter can run arbitrary SQL/Java (CREATE ALIAS) and would enable
+      // remote code execution here too (CVE-2026-41042 bypass via lakehouse-paimon).
+      String jdbcUri = paimonConfig.get(CATALOG_URI);
+      if (StringUtils.isNotBlank(jdbcUri)) {
+        String decodedUri = recursiveDecode(jdbcUri.toLowerCase());
+        if (decodedUri.startsWith("jdbc:h2")) {
+          throw new GravitinoRuntimeException(
+              "H2 JDBC URL is not allowed in catalog configuration");
+        }
+      }
       String driverClassName = paimonConfig.getJdbcDriver();
+      if (driverClassName != null && driverClassName.toLowerCase().startsWith("org.h2.")) {
+        throw new GravitinoRuntimeException(
+            "H2 JDBC driver is not allowed in catalog configuration");
+      }
       try {
         // Load the jdbc driver
         Class.forName(driverClassName);
@@ -148,6 +167,23 @@ public class CatalogUtils {
     }
   }
 
+  private static String recursiveDecode(String url) {
+    String prev;
+    String decoded = url;
+    int max = 5;
+
+    do {
+      prev = decoded;
+      try {
+        decoded = URLDecoder.decode(prev, "UTF-8");
+      } catch (Exception e) {
+        throw new GravitinoRuntimeException("Unable to decode JDBC URL");
+      }
+    } while (!prev.equals(decoded) && --max > 0);
+
+    return decoded;
+  }
+
   public static Map<String, String> toInnerProperty(
       Map<String, String> properties, boolean keepUnknown) {
     Map<String, String> gravitinoConfig = new HashMap<>();
