You can use concatenation to create your string. This does not raise a security warning. And preferable for clarity, when it comes to long SQL statements that would be better written, breaking into many lines
Using variables to build a string triggers a security warning.
This will result in a warning:
String columnName = getName(); String tableName = getTableName(); final String sql = "SELECT MAX(" + columnName + ") FROM " + tableName; PreparedStatement ps = connection.prepareStatement(sql);
This will not work:
String columnName = getName(); String tableName = getTableName(); final String sql = "SELECT MAX(" + "?" + ")" + "FROM " + "?"; PreparedStatement ps = connection.prepareStatement(sql); ps.setString(1, columnName); ps.setString(2, tableName);
This does not work, because prepared statements only allow you to bind parameters to the "values" bits of the SQL statement.
This is a solution that works:
private static final boolean USE_TEST_TABLE = true; private static final boolean USE_RESTRICTED_COL = true; private static final String TEST_TABLE = "CLIENT_TEST"; private static final String PROD_TABLE = "CLIENT"; private static final String RESTRICTED_COL ="AGE_COLLATED"; private static final String UNRESTRICTED_COL ="AGE"; .................... final String sql = "SELECT MAX(" + ( USE_RESTRICTED_COL ? RESTRICTED_COL : UNRESTRICTED_COL ) + ")" + "FROM " + ( USE_TEST_TABLE ? TEST_TABLE : PROD_TABLE ); PreparedStatement ps = connectComun.prepareStatement(sql);
But it only works if you need to choose between two tables whose names are known at compile time. You can use compound ternary operators for more than two cases, but then it becomes unreadable.
The first case may be a security issue if getName () or getTableName () gets the name from untrusted sources.
It is possible to build a secure SQL statement using variables if these variables have been previously validated. This is your case, but FindBugs cannot figure it out. Findbugs cannot know which sources trust or not.
But if you must use the column or table name from the user or untrusted input, then there is no way around it. You must confirm yourself with this line and ignore the Findbugs warning by any of the methods suggested in the other answers.
Conclusion There is no ideal solution for the general case of this question.