jeecgboot/JeecgBoot · critical · JeecgSqlInjectionException

请注意,值可能存在SQL注入风险!--->{value}

Error message

请注意,值可能存在SQL注入风险!--->{value}

What it means

Thrown by SqlInjectionUtil.filterContent(String,String) during the default keyword-text check (step 二) when the lowercased input contains any token from XSS_STR (e.g. 'select ', 'and ', 'or ', ';', '--', 'drop ', 'union' patterns). Raises JeecgSqlInjectionException. This is the strict general-purpose SQL-injection filter used across query parameters.

Source

Thrown at jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/SqlInjectionUtil.java:135

	 * @return
	 */
	public static void filterContent(String value, String customXssString) {
		if (value == null || "".equals(value)) {
			return;
		}
		// 一、校验sql注释 不允许有sql注释
		checkSqlAnnotation(value);
		// 转为小写进行后续比较
		value = value.toLowerCase().trim();
		
		// 二、SQL注入检测存在绕过风险 (普通文本校验)
		//https://gitee.com/jeecg/jeecg-boot/issues/I4NZGE
		String[] xssArr = XSS_STR.split("\\|");
		for (int i = 0; i < xssArr.length; i++) {
			if (value.indexOf(xssArr[i]) > -1) {
				log.error(SqlInjectionUtil.SQL_INJECTION_KEYWORD_TIP, xssArr[i]);
				log.error(SqlInjectionUtil.SQL_INJECTION_TIP_VARIABLE, value);
				throw new JeecgSqlInjectionException(SqlInjectionUtil.SQL_INJECTION_TIP + value);
			}
		}
		// 三、SQL注入检测存在绕过风险 (自定义传入普通文本校验)
		if (customXssString != null) {
			String[] xssArr2 = customXssString.split("\\|");
			for (int i = 0; i < xssArr2.length; i++) {
				if (value.indexOf(xssArr2[i]) > -1) {
					log.error(SqlInjectionUtil.SQL_INJECTION_KEYWORD_TIP, xssArr2[i]);
					log.error(SqlInjectionUtil.SQL_INJECTION_TIP_VARIABLE, value);
					throw new JeecgSqlInjectionException(SqlInjectionUtil.SQL_INJECTION_TIP + value);
				}
			}
		}

		// 四、SQL注入检测存在绕过风险 (正则校验)
		for (String regularOriginal : XSS_REGULAR_STR_ARRAY) {
			String regular = ".*" + regularOriginal + ".*";
			if (Pattern.matches(regular, value)) {

View on GitHub (pinned to 96fb33f5ec)

Solutions

  1. Do not pass free-form user text through filterContent for dynamic SQL; use parameterized queries / MyBatis placeholders instead.
  2. For field/table names use the dedicated validators getSqlInjectField / getSqlInjectTableName which enforce an allowlist regex rather than keyword blocking.
  3. If the value is legitimately a keyword-containing string, sanitize or whitelist it before it reaches dynamic SQL, or avoid concatenating it into SQL entirely.
  4. Review the value shown in the log (SQL_INJECTION_TIP_VARIABLE) to identify which input triggered it.

Example fix

// before — concatenating user input into SQL
String sql = "select * from t where name = '" + name + "'";
SqlInjectionUtil.filterContent(name, null);

// after — parameterized
Map<String,Object> params = new HashMap<>();
params.put("name", name);
String sql = "select * from t where name = #{name}";
Defensive patterns

Strategy: validation

Validate before calling

// Prefer structural validation over keyword filtering for identifiers
if (!value.matches("^[a-zA-Z0-9_]+$")) {
    throw new IllegalArgumentException("参数仅允许字母数字下划线");
}

Type guard

null

Try / catch

try {
    SqlInjectionUtil.filterContent(value, null);
} catch (JeecgSqlInjectionException e) {
    log.warn("SQL 注入检测拦截: {}", e.getMessage());
    throw new IllegalArgumentException("输入包含非法字符");
}

Prevention

When it happens

Trigger: filterContent is called on a value that contains a blacklisted substring such as 'select', 'insert', 'delete', 'update', 'drop', ';', '--', 'or ' (with trailing space). Common when a sort field, query param, or table name contains these words.

Common situations: A legitimate column name or value that coincidentally contains a keyword (e.g. a field named 'update_time' with a trailing context, or text content like 'delete this'); user free-text passed into a dynamic SQL fragment; ordering/search field injection.

Related errors


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