diff --git a/ruby/ql/lib/codeql/ruby/frameworks/Sqlite3.model.yml b/ruby/ql/lib/codeql/ruby/frameworks/Sqlite3.model.yml new file mode 100644 index 00000000000..e6aeb2c8240 --- /dev/null +++ b/ruby/ql/lib/codeql/ruby/frameworks/Sqlite3.model.yml @@ -0,0 +1,6 @@ +extensions: + - addsTo: + pack: codeql/ruby-all + extensible: summaryModel + data: + - ['SQLite3::Database!', 'Method[quote]', 'Argument[0]', 'ReturnValue', 'taint'] diff --git a/ruby/ql/lib/codeql/ruby/frameworks/Sqlite3.qll b/ruby/ql/lib/codeql/ruby/frameworks/Sqlite3.qll index f3e7626f733..1cf167baa72 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/Sqlite3.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/Sqlite3.qll @@ -76,26 +76,4 @@ module Sqlite3 { override DataFlow::Node getSql() { result = this.getArgument(0) } } - - /** - * A call to `SQLite3::Database.quote`, considered as a sanitizer for SQL statements. - */ - private class SQLite3QuoteSanitization extends SqlSanitization { - SQLite3QuoteSanitization() { - this = API::getTopLevelMember("SQLite3").getMember("Database").getAMethodCall("quote") - } - } - - /** - * Flow summary for `SQLite3::Database.quote()`. - */ - private class QuoteSummary extends SummarizedCallable::Range { - QuoteSummary() { this = "SQLite3::Database.quote()" } - - override MethodCall getACall() { result = any(SQLite3QuoteSanitization c).asExpr().getExpr() } - - override predicate propagatesFlow(string input, string output, boolean preservesValue) { - input = "Argument[0]" and output = "ReturnValue" and preservesValue = false - } - } } diff --git a/ruby/ql/test/library-tests/frameworks/sqlite3/SqlInjection.expected b/ruby/ql/test/library-tests/frameworks/sqlite3/SqlInjection.expected index e094f9603c8..47bbcc10c27 100644 --- a/ruby/ql/test/library-tests/frameworks/sqlite3/SqlInjection.expected +++ b/ruby/ql/test/library-tests/frameworks/sqlite3/SqlInjection.expected @@ -1,12 +1,25 @@ #select | sqlite3.rb:29:16:29:67 | "select * from table where cat..." | sqlite3.rb:25:16:25:21 | call to params | sqlite3.rb:29:16:29:67 | "select * from table where cat..." | This SQL query depends on a $@. | sqlite3.rb:25:16:25:21 | call to params | user-provided value | +| sqlite3.rb:33:16:33:77 | "select * from table where cat..." | sqlite3.rb:25:16:25:21 | call to params | sqlite3.rb:33:16:33:77 | "select * from table where cat..." | This SQL query depends on a $@. | sqlite3.rb:25:16:25:21 | call to params | user-provided value | edges | sqlite3.rb:25:5:25:12 | category | sqlite3.rb:29:16:29:67 | "select * from table where cat..." | provenance | AdditionalTaintStep | +| sqlite3.rb:25:5:25:12 | category | sqlite3.rb:32:50:32:57 | category | provenance | | | sqlite3.rb:25:16:25:21 | call to params | sqlite3.rb:25:16:25:32 | ...[...] | provenance | | | sqlite3.rb:25:16:25:32 | ...[...] | sqlite3.rb:25:5:25:12 | category | provenance | | +| sqlite3.rb:32:5:32:22 | sanitized_category | sqlite3.rb:33:16:33:77 | "select * from table where cat..." | provenance | AdditionalTaintStep | +| sqlite3.rb:32:26:32:58 | call to quote | sqlite3.rb:32:5:32:22 | sanitized_category | provenance | | +| sqlite3.rb:32:50:32:57 | category | sqlite3.rb:32:26:32:58 | call to quote | provenance | MaD:1 | +models +| 1 | Summary: SQLite3::Database!; Method[quote]; Argument[0]; ReturnValue; taint | nodes | sqlite3.rb:25:5:25:12 | category | semmle.label | category | | sqlite3.rb:25:16:25:21 | call to params | semmle.label | call to params | | sqlite3.rb:25:16:25:32 | ...[...] | semmle.label | ...[...] | | sqlite3.rb:29:16:29:67 | "select * from table where cat..." | semmle.label | "select * from table where cat..." | +| sqlite3.rb:32:5:32:22 | sanitized_category | semmle.label | sanitized_category | +| sqlite3.rb:32:26:32:58 | call to quote | semmle.label | call to quote | +| sqlite3.rb:32:50:32:57 | category | semmle.label | category | +| sqlite3.rb:33:16:33:77 | "select * from table where cat..." | semmle.label | "select * from table where cat..." | subpaths +testFailures +| sqlite3.rb:33:16:33:77 | "select * from table where cat..." | Unexpected result: Alert |