[0.16] disallow preparing statements that look like `SELECT * FROM ...`
A prepared statement that has a SELECT * in it is unsafe.
More details here:
- https://docs.datastax.com/en/developer/java-driver/3.0/manual/statements/prepared/#avoid-preparing-select-queries
- https://issues.apache.org/jira/browse/CASSANDRA-10786
This is a very very bad footgun, and can cause your driver to return incorrect rows when a table is altered.
We should disallow these kind of queries from being prepared, as it can introduce soundness bugs in one's code.
Ouch! Yes, that's an unpleasant one indeed. It's a pity that Cassandra still doesn't protect us from this.
However, is there a sensible way to spot this without fully parsing the query? I guess just checking for statements starting with /SELECT +\*/i would go a long way.
Our Python wrapper for cassandra has the following check when preparing statements, which seems to work good enough!
def assert_safe_prepared_statement(query_string: str) -> None:
query_tokens = [p.strip() for p in query_string.lower().strip().split()]
if len(query_tokens) >= 2 and query_tokens[0] == 'select' and query_tokens[1] == '*':
raise ValueError('Cannot prepare `select *` like statement. The query_string was %r' % query_string)
I think we can make the Rust one a bit more idiomatic with this:
fn is_unsafe_prepared_statement(query: &str) -> bool {
let mut tokens = query.split_ascii_whitespace();
match tokens.next() {
Some(tok) if tok.to_ascii_lowercase() == "select" => { }
_ => return false,
}
match tokens.next() {
Some(tok) if tok == "*" => true,
_ => false
}
}
Yep, looks good to me - it's best efforts but it will catch most badness.