{"record":{"id":"eabf42fd0598af62","repo":"hs-web/hsweb-framework","slug":"error-illegal-column-name","errorCode":"error.illegal_column_name","errorMessage":"error.illegal_column_name","messagePattern":"error\\.illegal_column_name","errorType":"validation","errorClass":"BusinessException.NoStackTrace","httpStatus":400,"severity":"error","filePath":"hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/query/QueryHelperUtils.java","lineNumber":58,"sourceCode":"                    return _col;\n                }\n                if (c == '_') {\n                    if (i == len - 1) {\n                        builder.append('_');\n                    } else {\n                        builder.append(Character.toUpperCase(_col.charAt(++i)));\n                    }\n                } else {\n                    builder.append(Character.toLowerCase(c));\n                }\n            }\n            return builder.toString();\n        });\n    }\n\n    public static void assertLegalColumn(String col) {\n        if (!isLegalColumn(col)) {\n            throw new BusinessException.NoStackTrace(\"error.illegal_column_name\", col);\n        }\n    }\n\n    public static boolean isLegalColumn(String col) {\n        int len = col.length();\n        for (int i = 0; i < len; i++) {\n            char c = col.charAt(i);\n            if (c == '_' || c == '$' || Character.isLetterOrDigit(c)) {\n                continue;\n            }\n            return false;\n        }\n        return true;\n    }\n}\n","sourceCodeStart":40,"sourceCodeEnd":74,"githubUrl":"https://github.com/hs-web/hsweb-framework/blob/b2cfc85a57c70bf5b5cf6e7edae2d37102652ec8/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/query/QueryHelperUtils.java#L40-L74","documentation":"QueryHelperUtils.assertLegalColumn validates that a column identifier used in dynamic sorting/querying contains only legal characters (letters, digits, underscore, dot, backtick etc.). Anything else — typically SQL injection attempts like `name;drop table` or `name) and 1=1` — raises BusinessException with the message code `error.illegal_column_name`.","triggerScenarios":"Calling QueryHelperUtils.assertLegalColumn (directly or via QueryHelper sort/dynamic query processing) with a column string containing characters outside the allowed set, e.g. whitespace, parentheses, semicolons, quotes, or SQL keywords.","commonSituations":"Malicious or buggy clients passing raw query/sort parameters into hsweb dynamic query endpoints; i18n resource missing so only the code is shown; fields containing dashes from JSON-style naming.","solutions":["Sanitize the column identifier before passing it: allow only [A-Za-z0-9_.] and map camelCase to snake_case.","Validate/sort parameters on the controller layer against a whitelist of sortable fields.","Add the message key `error.illegal_column_name` to your i18n bundle so users see a readable message."],"exampleFix":"// before\nString col = request.getParam(\"sortBy\"); // \"name;drop table x\"\nQueryHelperUtils.assertLegalColumn(col);\n// after\nif (!col.matches(\"[a-zA-Z0-9_.]+\")) { col = \"id\"; }\nQueryHelperUtils.assertLegalColumn(col);","handlingStrategy":"try-catch","validationCode":"if (col == null || !col.matches(\"[a-zA-Z0-9_.`]+\")) { throw new BadRequestException(\"illegal column name\"); }","typeGuard":null,"tryCatchPattern":"try { QueryHelperUtils.assertLegalColumn(sortBy); } catch (BusinessException e) { if (\"error.illegal_column_name\".equals(e.getCode())) { throw new BadRequestException(\"invalid sort field\"); } throw e; }","preventionTips":["Whitelist sortable/filterable fields in controllers","Reject raw client input as column identifiers","Keep i18n messages for error.illegal_column_name up to date"],"tags":["sql-injection","validation","column-name","business-exception"],"backgroundTag":"invalid-identifier-format","analyzedSha":"b2cfc85a57c70bf5b5cf6e7edae2d37102652ec8","analyzedAt":"2026-09-13T09:05:02.172Z","contentChangedAt":"2026-09-13T09:05:02.172Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}