hibernate/hibernate-orm · error · SemanticException

Function [" + functionName.toLowerCase() + "] is not allowed

Error message

Function [" + functionName.toLowerCase() + "] is not allowed in safe mode

What it means

Thrown as SemanticException by SqmUtil.failIfSafeModeEnabled when safe mode is on and a disallowed function is used in HQL or Criteria. Safe mode (hibernate.query.safe_mode_enabled, QuerySettings.SAFE_MODE_ENABLED, default false, incubating since Hibernate 8.0) hardens queries against untrusted input: only explicitly registered/contributed functions are permitted, and escape hatches like the 'sql()' and 'column()' fragments in Criteria are blocked outright. The message lowercases the function name, e.g. 'Function [sql] is not allowed in safe mode'.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmUtil.java:1416

					if ( !(parameter instanceof ValueBindJpaCriteriaParameter) ) {
						parameterExpressions.add( parameter );
					}
				}
				yield unmodifiableSet( parameterExpressions );
			}
		};
	}

	/**
	 * Throws a {@link SemanticException} if safe mode is enabled and the function is not allowed.
	 *
	 * @param safeModeEnabled whether safe mode is enabled
	 * @param functionName the name of the function to validate (will be converted to lowercase)
	 * @throws SemanticException if safe mode is enabled
	 */
	public static void failIfSafeModeEnabled(boolean safeModeEnabled, String functionName, @Nullable String queryString) {
		if ( safeModeEnabled ) {
			throw new SemanticException( "Function [" + functionName.toLowerCase() + "] is not allowed in safe mode", queryString );
		}
	}
}

View on GitHub (pinned to fad1729dce)

Solutions

  1. Contribute the function explicitly: implement org.hibernate.boot.model.FunctionContributor and register the function via FunctionContributions.getFunctionRegistry()
  2. Replace the blocked call with a registered dialect function or a normal HQL/Criteria expression
  3. If all queries are trusted, disable safe mode (remove hibernate.query.safe_mode_enabled=true)
  4. Keep user-supplied HQL in a separate SessionFactory configured with safe mode, and route internal trusted queries through a normal one

Example fix

// before: hibernate.query.safe_mode_enabled=true and HQL 'select reverse(p.name) from Person p' -> SemanticException
// after: contribute the function so safe mode accepts it
public class MyFunctionContributor implements FunctionContributor {
    @Override
    public void contributeFunctions(FunctionContributions contributions) {
        contributions.getFunctionRegistry().registerPattern(
                "reverse", "reverse(?1)",
                contributions.getTypeConfiguration().getBasicTypeRegistry().resolve(String.class)
        );
    }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// before executing user-supplied HQL with safe mode on, screen the function names it may call
static final Set<String> ALLOWED = Set.of("lower", "upper", "length", "substring", "concat");
static boolean onlyAllowedFunctions(String hql) {
    Matcher m = Pattern.compile("([A-Za-z_][A-Za-z0-9_]*)\\s*\\(").matcher(hql);
    while (m.find()) {
        if (!ALLOWED.contains(m.group(1).toLowerCase(Locale.ROOT))) return false;
    }
    return true;
}

Try / catch

try {
    return session.createSelectionQuery(userHql, Object[].class).getResultList();
} catch (SemanticException e) {
    if (e.getMessage() != null && e.getMessage().contains("safe mode")) {
        // unregistered function: reject the query, do not silently disable safe mode
        throw new SecurityException("Query uses a function not allowed in safe mode", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Setting hibernate.query.safe_mode_enabled=true (e.g. to accept HQL from users) and then executing queries that call unregistered functions; Criteria code using cb.function("sql", ...) or the sql()/column() escape APIs (SqmCriteriaNodeBuilder calls this check with name "sql" and "column"); custom dialect functions used in HQL that were never contributed through a FunctionContributor.

Common situations: Enabling safe mode for a query-builder/reporting feature that stores user-written HQL; upgrading to Hibernate 8 where the flag exists and ops turns it on globally; applications relying on ad-hoc SQL fragments inside criteria; multi-tenant products that must not let tenants call arbitrary DB functions.

Related errors


AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22). Data as JSON: /api/errors/7482c4e3d24abc6a. Report an issue: GitHub.