jeecgboot/JeecgBoot · critical · JeecgSqlInjectionException

字段不合法,存在SQL注入风险!--->

Error message

字段不合法,存在SQL注入风险!--->{field}

What it means

Thrown by SqlInjectionUtil.getSqlInjectField when a field/column name fails the fieldPattern regex (letters, digits, underscore only — no spaces, quotes, or escape sequences). It guards column lists used in dynamic SELECT/ORDER BY/WHERE construction. After the regex, filterContentMulti() runs an additional keyword blacklist pass. The error exists because column names are concatenated into SQL rather than parameterized.

Solutions

  1. Ensure the field value is a single bare column identifier matching ^[A-Za-z][A-Za-z0-9_]*$ before calling getSqlInjectField.
  2. If you need multiple columns, split on comma first and call getSqlInjectField(String[]) so each is validated independently.
  3. Never allow aliases, functions, or expressions through this API; map display labels to physical columns via a whitelist map.
  4. Add a server-side enum/whitelist of permitted sort columns per entity and reject anything not in it.

Example fix

// before
String field = "create_time DESC";
SqlInjectionUtil.getSqlInjectField(field); // throws

// after
String col = field.split(" ")[0];
String dir = field.endsWith("DESC") ? "DESC" : "ASC";
SqlInjectionUtil.getSqlInjectField(col);
Defensive patterns

Strategy: validation

Validate before calling

private static final Pattern FIELD = Pattern.compile("^[A-Za-z][A-Za-z0-9_]*$");
public List<String> safeColumns(String csv){
    return Arrays.stream(csv.split(","))
        .map(String::trim)
        .filter(c -> FIELD.matcher(c).matches())
        .collect(Collectors.toList());
}

Type guard

public static boolean isValidField(String f){
    return f != null && f.matches("^[A-Za-z][A-Za-z0-9_]*$");
}

Try / catch

try {
    SqlInjectionUtil.getSqlInjectField(fields);
} catch (JeecgSqlInjectionException e) {
    return Collections.emptyList(); // or badRequest
}

Prevention

When it happens

Trigger: Submitting a grid/query request whose 'column' or 'field' parameter contains 'user_name AS u', 'id,1=1', 'name`', a function call like 'COUNT(*)', an aliased field with a space, or a column with a quote/parenthesis. Common in online-report sort fields, list-view field selectors, and code-gen column definitions.

Common situations: Frontend sending a display alias instead of the physical column, users pasting a full SQL fragment into a single-column field, multi-column sort params concatenated before validation, or an attempt at UNION/subquery injection through an order-by column.

Related errors


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

Appendix: source

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

			return field;
		}
		
		field = field.trim();

		if (field.contains(SymbolConstant.COMMA)) {
			return getSqlInjectField(field.split(SymbolConstant.COMMA));
		}

		/**
		 * 校验表字段是否有效
		 *
		 * 字段定义只能是是字母 数字 下划线的组合(不允许有空格、转义字符串等)
		 */
		boolean isValidField = fieldPattern.matcher(field).matches();
		if (!isValidField) {
			String errorMsg = "字段不合法,存在SQL注入风险!--->" + field;
			log.error(errorMsg);
			throw new JeecgSqlInjectionException(errorMsg);
		}

		//进一步验证是否存在SQL注入风险
		filterContentMulti(field);
		return field;
	}

	/**
	 * 获取多个字段
	 * 返回: 逗号拼接
	 *
	 * @param fields
	 * @return
	 */
	public static String getSqlInjectField(String... fields) {
		for (String s : fields) {
			getSqlInjectField(s);
		}

View on GitHub (pinned to 96fb33f5ec)