This is an automated email from the ASF dual-hosted git repository.
yuqi1129 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gravitino.git
The following commit(s) were added to refs/heads/main by this push:
new 5daabcd0e8 [MINOR] fix(catalog): block H2 JDBC URL and driver in
catalog datasource creation (#10801)
5daabcd0e8 is described below
commit 5daabcd0e8ddc96e25bd6c6ce7b153cdb311c3f2
Author: Jerry Shao <[email protected]>
AuthorDate: Mon Apr 20 19:37:06 2026 +0800
[MINOR] fix(catalog): block H2 JDBC URL and driver in catalog datasource
creation (#10801)
### What changes were proposed in this pull request?
Block H2 JDBC URLs and H2 driver class names in
`DataSourceUtils.createDataSource()`, which is the entry point for all
user-facing catalog JDBC connections.
The check is intentionally scoped to `DataSourceUtils` and not added to
the shared `JdbcUrlUtils.validateJdbcConfig()`, because that utility is
also called by the internal entity store (`SqlSessionFactoryHelper`)
which legitimately uses H2 as an embedded backend.
### Why are the changes needed?
H2 is only used as an embedded backend for Gravitino's internal entity
store and should not be used through user-facing catalog configuration.
### Does this PR introduce _any_ user-facing change?
Catalog creation or `testConnection` calls that supply an H2 JDBC URL
(e.g. `jdbc:h2:...`) or H2 driver class (e.g. `org.h2.Driver`) will now
be rejected with a clear error message. The check is case-insensitive.
### How was this patch tested?
Added 4 tests to `TestDataSourceUrlValidation`:
- `testRejectH2Url` — blocks H2 URL
- `testRejectH2UrlCaseInsensitive` — blocks `JDBC:H2:...` (uppercase)
- `testRejectH2Driver` — blocks `org.h2.Driver` with a non-H2 URL
- `testRejectH2DriverCaseInsensitive` — blocks `ORG.H2.DRIVER`
Co-authored-by: Claude Sonnet 4.6 <[email protected]>
---
.../catalog/jdbc/utils/DataSourceUtils.java | 11 ++++
.../jdbc/utils/TestDataSourceUrlValidation.java | 63 ++++++++++++++++++++++
.../org/apache/gravitino/utils/JdbcUrlUtils.java | 1 -
3 files changed, 74 insertions(+), 1 deletion(-)
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 59da59b770..a2b8e12b80 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,17 @@ public class DataSourceUtils {
public static DataSource createDataSource(JdbcConfig jdbcConfig)
throws GravitinoRuntimeException {
+ // H2 is bundled as an embedded backend and must not be used through
user-facing catalog
+ // configuration. Its INIT parameter allows arbitrary SQL (and Java code
via CREATE ALIAS)
+ // to execute at connection time, and the H2 driver class must also be
blocked to prevent
+ // bypassing this check via a mismatched driver and URL combination.
+ String decodedUrl = recursiveDecode(jdbcConfig.getJdbcUrl().toLowerCase());
+ if (decodedUrl.startsWith("jdbc:h2")) {
+ throw new GravitinoRuntimeException("H2 JDBC URL is not allowed in
catalog configuration");
+ }
+ if (jdbcConfig.getJdbcDriver().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-jdbc-common/src/test/java/org/apache/gravitino/catalog/jdbc/utils/TestDataSourceUrlValidation.java
b/catalogs/catalog-jdbc-common/src/test/java/org/apache/gravitino/catalog/jdbc/utils/TestDataSourceUrlValidation.java
index a8a98b5faa..e05e4f1062 100644
---
a/catalogs/catalog-jdbc-common/src/test/java/org/apache/gravitino/catalog/jdbc/utils/TestDataSourceUrlValidation.java
+++
b/catalogs/catalog-jdbc-common/src/test/java/org/apache/gravitino/catalog/jdbc/utils/TestDataSourceUrlValidation.java
@@ -84,4 +84,67 @@ public class TestDataSourceUrlValidation {
Assertions.assertThrows(
GravitinoRuntimeException.class, () ->
DataSourceUtils.createDataSource(properties));
}
+
+ @Test
+ public void testRejectH2Url() {
+ HashMap<String, String> properties = Maps.newHashMap();
+ properties.put(JdbcConfig.JDBC_DRIVER.getKey(), "org.postgresql.Driver");
+ properties.put(
+ JdbcConfig.JDBC_URL.getKey(),
+ "jdbc:h2:mem:test;INIT=CREATE ALIAS EXEC AS 'String f() throws
Exception"
+ + " { Runtime.getRuntime().exec(\"id\"); return \"ok\"; }'\\;CALL
EXEC()");
+ properties.put(JdbcConfig.USERNAME.getKey(), "test");
+ properties.put(JdbcConfig.PASSWORD.getKey(), "test");
+
+ GravitinoRuntimeException gre =
+ Assertions.assertThrows(
+ GravitinoRuntimeException.class, () ->
DataSourceUtils.createDataSource(properties));
+ Assertions.assertEquals(
+ "H2 JDBC URL is not allowed in catalog configuration",
gre.getMessage());
+ }
+
+ @Test
+ public void testRejectH2UrlCaseInsensitive() {
+ HashMap<String, String> properties = Maps.newHashMap();
+ properties.put(JdbcConfig.JDBC_DRIVER.getKey(), "org.postgresql.Driver");
+ properties.put(JdbcConfig.JDBC_URL.getKey(), "JDBC:H2:mem:test");
+ properties.put(JdbcConfig.USERNAME.getKey(), "test");
+ properties.put(JdbcConfig.PASSWORD.getKey(), "test");
+
+ GravitinoRuntimeException gre =
+ Assertions.assertThrows(
+ GravitinoRuntimeException.class, () ->
DataSourceUtils.createDataSource(properties));
+ Assertions.assertEquals(
+ "H2 JDBC URL is not allowed in catalog configuration",
gre.getMessage());
+ }
+
+ @Test
+ public void testRejectH2Driver() {
+ HashMap<String, String> properties = Maps.newHashMap();
+ properties.put(JdbcConfig.JDBC_DRIVER.getKey(), "org.h2.Driver");
+ properties.put(JdbcConfig.JDBC_URL.getKey(),
"jdbc:postgresql://localhost:5432/test");
+ properties.put(JdbcConfig.USERNAME.getKey(), "test");
+ properties.put(JdbcConfig.PASSWORD.getKey(), "test");
+
+ GravitinoRuntimeException gre =
+ Assertions.assertThrows(
+ GravitinoRuntimeException.class, () ->
DataSourceUtils.createDataSource(properties));
+ Assertions.assertEquals(
+ "H2 JDBC driver is not allowed in catalog configuration",
gre.getMessage());
+ }
+
+ @Test
+ public void testRejectH2DriverCaseInsensitive() {
+ HashMap<String, String> properties = Maps.newHashMap();
+ properties.put(JdbcConfig.JDBC_DRIVER.getKey(), "ORG.H2.DRIVER");
+ properties.put(JdbcConfig.JDBC_URL.getKey(),
"jdbc:postgresql://localhost:5432/test");
+ properties.put(JdbcConfig.USERNAME.getKey(), "test");
+ properties.put(JdbcConfig.PASSWORD.getKey(), "test");
+
+ GravitinoRuntimeException gre =
+ Assertions.assertThrows(
+ GravitinoRuntimeException.class, () ->
DataSourceUtils.createDataSource(properties));
+ Assertions.assertEquals(
+ "H2 JDBC driver is not allowed in catalog configuration",
gre.getMessage());
+ }
}
diff --git a/common/src/main/java/org/apache/gravitino/utils/JdbcUrlUtils.java
b/common/src/main/java/org/apache/gravitino/utils/JdbcUrlUtils.java
index 04dab3e1dc..e157109f1b 100644
--- a/common/src/main/java/org/apache/gravitino/utils/JdbcUrlUtils.java
+++ b/common/src/main/java/org/apache/gravitino/utils/JdbcUrlUtils.java
@@ -76,7 +76,6 @@ public class JdbcUrlUtils {
String lowerUrl = url.toLowerCase();
String decodedUrl = recursiveDecode(lowerUrl);
- // As H2 is only used for testing, we do not check unsafe parameters for
H2.
if (decodedUrl.startsWith("jdbc:mysql")) {
checkUnsafeParameters(decodedUrl, all, UNSAFE_MYSQL_PARAMETERS, "MySQL");
} else if (decodedUrl.startsWith("jdbc:mariadb")) {