# Patch Analysis: CVE-2026-40900

## Fix Commit

- **SHA**: `15611593b3631b5a25528b9cdb2ee517ef27929a`
- **Message**: `fix: SQL Injection via Stacked Queries`
- **Author**: junjun <junjie.xia@fit2cloud.com>
- **Date**: Wed Apr 8 14:31:56 2026 +0800

## Files Changed

```
core/core-backend/src/main/java/io/dataease/datasource/type/Mysql.java
```

## Diff Summary

```diff
-    private List<String> illegalParameters = Arrays.asList("maxAllowedPacket", "autoDeserialize", "queryInterceptors", "statementInterceptors", "detectCustomCollations", "allowloadlocalinfile", "allowUrlInLocalInfile", "allowLoadLocalInfileInPath");
+    private List<String> illegalParameters = Arrays.asList("maxAllowedPacket", "autoDeserialize", "queryInterceptors", "statementInterceptors", "detectCustomCollations", "allowloadlocalinfile", "allowUrlInLocalInfile", "allowLoadLocalInfileInPath", "allowMultiQueries");
```

## How the Fix Works

1. `Mysql.getJdbc()` builds the JDBC URL from the datasource configuration (host, port, database, extraParams).
2. Before returning the URL, it calls `JdbcUrlSecurityPolicy.validate("mysql", getDriver(), jdbcUrl, getExtraParams())`.
3. `validate` iterates over `illegalParameters` and throws `DEException` if any parameter is found in the URL or extraParams.
4. In v2.10.20, `allowMultiQueries` was **not** in `illegalParameters`, so a datasource with `extraParams=allowMultiQueries=true` passed validation.
5. In v2.10.21, adding `"allowMultiQueries"` to the list causes `validate` to reject the URL.
6. During datasource save/update (`DatasourceServer.save()` / `update()`), `checkDatasourceStatus()` calls `provider.checkStatus()`, which invokes `getConnection()` → `configuration.getJdbc()` → `validate()`. The validation failure throws an exception that is caught inside `save()`, setting `status="Error"`.
7. `DatasetDataManage.previewSql()` checks `datasourceSchemaDTO.getStatus()` and throws `i18n_invalid_ds` if it is `"Error"`, preventing the stacked SQL from ever reaching the database.

## Verification

The reproduction script confirms:
- **v2.10.20**: datasource validates as `Success`, `previewSql` executes the stacked payload, and a side-effect row appears.
- **v2.10.21**: datasource save succeeds but with `status="Error"`; `previewSql` refuses to run, and no side-effect row appears.

## Limitations of the Fix

The patch blocks the **prerequisite** (`allowMultiQueries=true`) rather than the **root cause** (lack of single-statement validation in `previewSql`). A more robust fix would also:
- Parse the user SQL in `previewSql` to ensure it is a single SELECT statement before wrapping it.
- Reject any payload containing statement terminators (`;`) or comment sequences that could break out of the wrapper.

These additional checks are not present in v2.10.21, so if an attacker finds another way to set `allowMultiQueries=true` (e.g., via a different JDBC parameter encoding, a custom driver, or a future bypass in the blocklist), the `previewSql` endpoint remains potentially vulnerable.

## Recommendation

Apply the vendor patch (upgrade to v2.10.21+) and consider adding server-side SQL-structure validation in `DatasetDataManage.previewSql()` as defense-in-depth.
