jeecgboot/JeecgBoot · critical · JeecgBootException

连接地址有安全风险,包含不安全参数【{unsafeParam}】

Error message

连接地址有安全风险,包含不安全参数【{unsafeParam}】

What it means

Thrown by JdbcSecurityUtil.validate() when a JDBC connection URL contains a parameter from the UNSAFE_PARAMS blacklist. This protects against JDBC deserialization/RCE attacks (e.g., MySQL autoDeserialize, PostgreSQL socketFactory, H2 INIT/RUNSCRIPT). The check uses full-URL case-insensitive contains matching, covering all parameter separator formats (?, ;, (), address=). Called from DynamicDBUtil.addDynamicDataSource() and SysDataSourceController add/update endpoints.

Source

Thrown at jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/security/JdbcSecurityUtil.java:113

            "org.h2.Driver",
    };

    /**
     * 校验 JDBC URL 是否包含危险参数
     *
     * @param jdbcUrl JDBC 连接地址
     * @throws JeecgBootException 包含危险参数时抛出
     */
    public static void validate(String jdbcUrl) {
        if (oConvertUtils.isEmpty(jdbcUrl)) {
            return;
        }

        String lowerUrl = jdbcUrl.toLowerCase();

        for (String unsafeParam : UNSAFE_PARAMS) {
            if (lowerUrl.contains(unsafeParam)) {
                throw new JeecgBootException("连接地址有安全风险,包含不安全参数【" + unsafeParam + "】");
            }
        }
    }

    /**
     * 校验驱动类名是否在白名单中
     *
     * @param driverClassName JDBC 驱动类名
     * @throws JeecgBootException 驱动不在白名单时抛出
     */
    public static void validateDriver(String driverClassName) {
        if (oConvertUtils.isEmpty(driverClassName)) {
            throw new JeecgBootException("数据库驱动类名不能为空");
        }
        for (String allowed : ALLOWED_DRIVERS) {
            if (allowed.equals(driverClassName)) {
                return;
            }

View on GitHub (pinned to 96fb33f5ec)

Solutions

  1. Remove the blacklisted parameter from the JDBC URL — review each parameter in the URL and strip any that match the UNSAFE_PARAMS list.
  2. If the parameter is genuinely needed for a legitimate use case, evaluate whether a safer alternative exists (e.g., use server-side SSL config instead of socketFactory).
  3. For H2 INIT scripts, move schema initialization out of the connection URL into a Flyway/Liquibase migration.
  4. Review the full UNSAFE_PARAMS array in JdbcSecurityUtil.java to see all blocked substrings.

Example fix

// before — MySQL URL with dangerous params
jdbc:mysql://host:3306/db?autoDeserialize=true&queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor

// after — safe URL without dangerous params
jdbc:mysql://host:3306/db?useSSL=true&serverTimezone=UTC
Defensive patterns

Strategy: validation

Validate before calling

// Strip known-dangerous params before validation (for audit purposes)
// Better: construct URLs without dangerous params from the start
String jdbcUrl = "jdbc:mysql://host:3306/db?useSSL=true&serverTimezone=UTC";
// Review UNSAFE_PARAMS in JdbcSecurityUtil.java to see all blocked substrings

Try / catch

try {
    JdbcSecurityUtil.validate(jdbcUrl);
} catch (JeecgBootException e) {
    log.error("JDBC URL rejected by security check: {}", e.getMessage());
    return Result.error("数据库连接地址包含不安全参数,请检查配置");
}

Prevention

When it happens

Trigger: Creating a dynamic data source with a JDBC URL containing 'allowLoadLocalInfile', 'autoDeserialize', 'socketFactory', 'INIT=', 'RUNSCRIPT', 'queryInterceptors', or any of the ~17 blacklisted parameter substrings. Triggered when an admin configures a new data source through the system data source management UI or API.

Common situations: Admin configures a data source with a copy-pasted JDBC URL from another project that includes performance tuning parameters (e.g., 'autoDeserialize=true' for legacy MySQL); H2 database URL with 'INIT=RUNSCRIPT FROM ...' for schema initialization; PostgreSQL URL with socketFactory for SSL; malicious user with data-source permissions attempting RCE.

Related errors


AI-assisted analysis of jeecgboot/JeecgBoot@96fb33f5ec (2026-08-14). Data as JSON: /api/errors/e36bf3ba0a9a53ce. Report an issue: GitHub.