We have a method in our database layer which looks like this:
public List<String> getNamesFromId(List<Long> idsList){
StringBuilder query = new StringBuilder();
query.append("Select first_name from person where id in (");
for (int pos = 0; pos < idsList.size(); pos++) {
query.append("?");
query.append(",");
}
query.deleteCharAt(query.length() - 1).append(")");
try {
conn = establishConnection();
pstmt = conn.prepareStatement(query.toString());
for (int i = 0; i < selections.size(); i++) {
pstmt.setLong(i + 1, idsList.get(i));
}
rs = pstmt.executeQuery();
} catch (SQLException e) {
//
}
try {
List<String> namesList = new ArrayList<String>();
while (rs.next()) {
namesList.add(rs.getString("FIRST_NAME"));
}
} catch (SQLException e) {
//
}
// close the Connection object
try {
rs.close();
pstmt.close();
conn.close();
} catch (SQLException e) {
//
}
During our fortify scan it is flagging this as SQL Injection saying "invokes a SQL query built using input potentially coming from an untrusted source. This call could allow an attacker to modify the statement's meaning or to execute arbitrary SQL commands."
Is this because this is a public facing method and we are passing in the parameters for the IN part of the prepared statement? If so how can we do it better? Or is it a false alarm from fortify?