baomidou/mybatis-plus · error · MybatisPlusException

Discovering SQL injection column: %s

Error message

Discovering SQL injection column: %s

What it means

UpdateWrapper.checkSqlInjection() opted this wrapper into SQL-injection screening, and a column string used in set/eq/condition building matched known injection patterns in SqlInjectionUtils. The wrapper rejects the value before the SQL reaches the database.

Source

Thrown at mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/conditions/update/UpdateWrapper.java:90


    /**
     * 检查 SQL 注入过滤
     */
    private boolean checkSqlInjection;

    /**
     * 开启检查 SQL 注入
     */
    public UpdateWrapper<T> checkSqlInjection() {
        this.checkSqlInjection = true;
        return this;
    }

    @Override
    protected String columnToString(String column) {
        if (checkSqlInjection && SqlInjectionUtils.check(column)) {
            throw new MybatisPlusException("Discovering SQL injection column: " + column);
        }
        return column;
    }

    @Override
    public String getSqlSet() {
        if (CollectionUtils.isEmpty(sqlSet)) {
            return null;
        }
        return String.join(Constants.COMMA, sqlSet);
    }

    @Override
    public UpdateWrapper<T> set(boolean condition, String column, Object val, String mapping) {
        return maybeDo(condition, () -> {
            String sql = formatParam(mapping, val);
            sqlSet.add(column + Constants.EQUALS + sql);
        });

View on GitHub (pinned to bf67d90747)

Solutions

  1. Use the two-argument form set("status", value) instead of embedding expressions in the column string
  2. Whitelist any dynamic column names coming from external input
  3. For legitimate identifiers flagged by the checker, apply proper DB identifier quoting rather than bypassing the check

Example fix

// before
uw.checkSqlInjection().set("name='a', role='admin'", null);
// after
uw.checkSqlInjection().set("name", "a").set("role", "admin");
Defensive patterns

Strategy: validation

Validate before calling

private static final Set<String> UPDATABLE = Set.of("name", "email", "status");
UpdateWrapper<User> uw = new UpdateWrapper<>().checkSqlInjection();
if (UPDATABLE.contains(field)) uw.set(field, value); else throw new IllegalArgumentException("Field not updatable: " + field);

Try / catch

try { uw.set(col, val); } catch (MybatisPlusException e) { audit.warn("Rejected set column {}", col); throw new BadRequestException("Invalid field"); }

Prevention

When it happens

Trigger: Calling updateWrapper.checkSqlInjection() and then passing a suspicious string as a column argument, e.g. set("name = 'x', role = 'admin'", value), or column strings built from raw request input.

Common situations: Using UpdateWrapper.set with a combined 'col = expr' string instead of set(column, value); front-end driven field names flowing into update conditions; test data containing quotes/semicolons used as a column name.

Related errors


AI-assisted analysis of baomidou/mybatis-plus@bf67d90747 (2026-08-14). Data as JSON: /api/errors/1d8559aec395795b. Report an issue: GitHub.