cassandra-rs icon indicating copy to clipboard operation
cassandra-rs copied to clipboard

[0.16] disallow preparing statements that look like `SELECT * FROM ...`

Open jhgg opened this issue 5 years ago • 3 comments

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.

jhgg avatar Jan 21 '21 23:01 jhgg

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.

kw217 avatar Jan 22 '21 13:01 kw217

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
    }
}

jhgg avatar Jan 23 '21 21:01 jhgg

Yep, looks good to me - it's best efforts but it will catch most badness.

kw217 avatar Feb 02 '21 11:02 kw217