pagehelper-org/Mybatis-PageHelper · error · PageException

count( ) has a risk of SQL injection

Error message

count(${countColumn}) has a risk of SQL injection

What it means

Page.setCountColumn validates the column used in the generated count query. Only "0", "*", or a value passing SqlSafeUtil's injection check are allowed; anything else throws a PageException. This protects the count(...) SQL, which cannot use bound parameters for the column list.

Solutions

  1. Use "*" (default) or "0" or a plain verified column name like "id".
  2. Sanitize/whitelist the column name before calling setCountColumn.
  3. If a distinct/expression count is required, write a custom count method in the mapper (count method id via countSuffix) instead of injecting an expression.
  4. Update config/property value to a simple column identifier.

Example fix

// before
page.setCountColumn(request.getParameter("col"));
// after
String col = request.getParameter("col");
if (col == null || !col.matches("[a-zA-Z0-9_]+")) {
    page.setCountColumn("*");
} else {
    page.setCountColumn(col);
}
Defensive patterns

Strategy: validation

Validate before calling

static void assertSafeCountColumn(String col) {
    if (!("*".equals(col) || "0".equals(col) || col.matches("[a-zA-Z0-9_]+"))) {
        throw new IllegalArgumentException("unsafe countColumn: " + col);
    }
}

Type guard

static boolean isSafeCountColumn(String s) {
    return "*".equals(s) || "0".equals(s) || (s != null && s.matches("[a-zA-Z0-9_]+"));
}

Try / catch

try {
    page.setCountColumn(column);
} catch (PageException e) {
    log.warn("Rejected countColumn: {}", column, e);
    page.setCountColumn("*");
}

Prevention

When it happens

Trigger: Calling Page.setCountColumn(String) (or the countColumn(...) helper / PageHelper.skip-style API that sets it) with a value like 'id) FROM users--' or any string containing quotes/comments that SqlSafeUtil rejects.

Common situations: Passing a user-supplied count column from a request parameter, or configuring countColumn in properties with a typo or expression such as 'distinct id' that the safe check flags.

Related errors


AI-assisted analysis of pagehelper-org/Mybatis-PageHelper@c692616c5b (2026-09-08). Data as JSON: /api/errors/648e722b746fff6b. Report an issue: GitHub.

Appendix: source

Thrown at src/main/java/com/github/pagehelper/Page.java:591

    public <E> PageSerializable<E> doSelectPageSerializable(ISelect select) {
        select.doSelect();
        return (PageSerializable<E>) this.toPageSerializable();
    }

    public long doCount(ISelect select) {
        this.pageSizeZero = true;
        this.pageSize = 0;
        select.doSelect();
        return this.total;
    }

    public String getCountColumn() {
        return countColumn;
    }

    public void setCountColumn(String countColumn) {
        if (!"0".equals(countColumn) && !"*".equals(countColumn) && SqlSafeUtil.check(countColumn)) {
            throw new PageException("count(" + countColumn + ") has a risk of SQL injection");
        }
        this.countColumn = countColumn;
    }

    public BoundSqlInterceptor getBoundSqlInterceptor() {
        return boundSqlInterceptor;
    }

    public void setBoundSqlInterceptor(BoundSqlInterceptor boundSqlInterceptor) {
        this.boundSqlInterceptor = boundSqlInterceptor;
    }

    BoundSqlInterceptor.Chain getChain() {
        return chain;
    }

    void setChain(BoundSqlInterceptor.Chain chain) {
        this.chain = chain;

View on GitHub (pinned to c692616c5b)