# Patch Analysis: CVE-2026-40900 (Variant Stage)

## Original Fix Commit

- **SHA**: `15611593b3631b5a25528b9cdb2ee517ef27929a`
- **Message**: `fix: SQL Injection via Stacked Queries`
- **Files Changed**: `core/core-backend/src/main/java/io/dataease/datasource/type/Mysql.java`

## What the Fix Changes

The fix adds the string `"allowMultiQueries"` to the `illegalParameters` list in `Mysql.java`. During datasource save/update, `Mysql.getJdbc()` calls `JdbcUrlSecurityPolicy.validate()` which iterates over `illegalParameters` and throws `DEException` if any parameter is found in the JDBC URL or `extraParams`. A datasource that fails validation is saved with `status="Error"`, and `DatasetDataManage.previewSql()` refuses to execute against Error datasources.

## Fix Assumptions

1. **MySQL-specific**: The fix assumes that multi-statement execution in `previewSql` is only possible when the MySQL JDBC driver is configured with `allowMultiQueries=true`.
2. **Blocklist sufficiency**: The fix assumes that a simple string blocklist (`illegalParameters`) is sufficient to prevent attackers from enabling multi-statements.
3. **All MySQL-compatible types covered**: The fix assumes that `mariadb`, `StarRocks`, `doris`, and `TiDB` datasource types, which parse their configuration as `Mysql.class`, inherit the same `illegalParameters` protection.
4. **Datasource-status check is enough**: The fix assumes that preventing `previewSql` from running against Error-status datasources is sufficient to block the exploit path.

## What the Fix Does NOT Cover

1. **Other database types with native multi-statement support**: PostgreSQL, SQL Server, and possibly other drivers support multi-statements by default without requiring a special JDBC parameter. The fix does not add any restriction for these types.
2. **The `previewSql` SQL-wrapping logic itself**: The endpoint still wraps raw user SQL in `SELECT * FROM ( <sql> ) tmp LIMIT 100` without parsing, validating, or sanitizing the input. There is no single-statement enforcement, no `;` rejection, and no comment-sequence filtering.
3. **Encoding bypasses of the blocklist**: `Mysql.java` (v2.10.21) uses `URLDecoder.decode(...).toLowerCase().contains(...)` for matching. This is vulnerable to bypasses where an encoded form of the parameter name does not match the lowercased blocklist string but is later decoded by the JDBC driver. In practice, MySQL Connector/J performs single-level decoding, so double-encoding (`%254D`) bypasses the check but is not recognized by the driver. However, other drivers or future versions might behave differently.
4. **Alternative endpoints that execute SQL without datasource-status checks**: `getFieldEnum` and `getFieldEnumDs` in `DatasetDataManage.java` do **not** call `DatasourceUtils.checkDsStatus()` before executing SQL. While they operate on saved datasets rather than raw SQL, this is a gap in the defense-in-depth strategy.

## Comparison of Behavior Before and After the Fix

| Scenario | v2.10.20 | v2.10.21 |
|----------|----------|----------|
| MySQL datasource with `allowMultiQueries=true` | `status=Success`, `previewSql` executes stacked SQL | `status=Error`, `previewSql` blocked |
| `mariadb` datasource with `allowMultiQueries=true` | `status=Success`, stacked SQL works (same MySQL driver) | `status=Error`, blocked |
| MySQL with double-encoded `allow%254DultiQueries=true` | `status=Success`, stacked SQL fails (driver doesn't recognize) | `status=Success`, stacked SQL fails (same driver limitation) |
| PostgreSQL datasource with stacked query payload | Stacked SQL executes (5s time delay confirmed) | Stacked SQL blocked (no delay, syntax error) |

## Conclusion

The patch is **incomplete**. It blocks the specific `allowMultiQueries` prerequisite for MySQL but leaves the root cause untouched:
- `previewSql` still lacks single-statement validation.
- Other database types (PostgreSQL, SQL Server) that support multi-statements natively are not restricted.
- The blocklist matching logic is fragile against encoding tricks.

A robust fix should validate the SQL structure in `previewSql` **and** harden the JDBC parameter validation.
