diff --git a/go/ql/lib/change-notes/2024-11-20-heuristic-logging-sinks.md b/go/ql/lib/change-notes/2024-11-20-heuristic-logging-sinks.md new file mode 100644 index 000000000000..46f5988b3798 --- /dev/null +++ b/go/ql/lib/change-notes/2024-11-20-heuristic-logging-sinks.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* A call to a method whose name starts with "Debug", "Error", "Fatal", "Info", "Log", "Output", "Panic", "Print", "Trace", "Warn" or "With" defined on an interface whose name ends in "logger" or "Logger" is now considered a LoggerCall. In particular, it is a sink for `go/clear-text-logging` and `go/log-injection`. This may lead to some more alerts in those queries. diff --git a/go/ql/lib/ext/database.sql.driver.model.yml b/go/ql/lib/ext/database.sql.driver.model.yml index c2d780bb7c86..10cfba9388a6 100644 --- a/go/ql/lib/ext/database.sql.driver.model.yml +++ b/go/ql/lib/ext/database.sql.driver.model.yml @@ -1,4 +1,14 @@ extensions: + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["database/sql/driver", "Execer", True, "Exec", "", "", "Argument[0]", "sql-injection", "manual"] + - ["database/sql/driver", "ExecerContext", True, "ExecContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["database/sql/driver", "Conn", True, "Prepare", "", "", "Argument[0]", "sql-injection", "manual"] + - ["database/sql/driver", "ConnPrepareContext", True, "PrepareContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["database/sql/driver", "Queryer", True, "Query", "", "", "Argument[0]", "sql-injection", "manual"] + - ["database/sql/driver", "QueryerContext", True, "QueryContext", "", "", "Argument[1]", "sql-injection", "manual"] - addsTo: pack: codeql/go-all extensible: summaryModel diff --git a/go/ql/lib/ext/database.sql.model.yml b/go/ql/lib/ext/database.sql.model.yml index e1083f6e49a6..5854ced527d5 100644 --- a/go/ql/lib/ext/database.sql.model.yml +++ b/go/ql/lib/ext/database.sql.model.yml @@ -1,4 +1,32 @@ extensions: + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["database/sql", "Conn", True, "Exec", "", "", "Argument[0]", "sql-injection", "manual"] + - ["database/sql", "Conn", True, "ExecContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["database/sql", "Conn", True, "Prepare", "", "", "Argument[0]", "sql-injection", "manual"] + - ["database/sql", "Conn", True, "PrepareContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["database/sql", "Conn", True, "Query", "", "", "Argument[0]", "sql-injection", "manual"] + - ["database/sql", "Conn", True, "QueryContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["database/sql", "Conn", True, "QueryRow", "", "", "Argument[0]", "sql-injection", "manual"] + - ["database/sql", "Conn", True, "QueryRowContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["database/sql", "DB", True, "Exec", "", "", "Argument[0]", "sql-injection", "manual"] + - ["database/sql", "DB", True, "ExecContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["database/sql", "DB", True, "Prepare", "", "", "Argument[0]", "sql-injection", "manual"] + - ["database/sql", "DB", True, "PrepareContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["database/sql", "DB", True, "Query", "", "", "Argument[0]", "sql-injection", "manual"] + - ["database/sql", "DB", True, "QueryContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["database/sql", "DB", True, "QueryRow", "", "", "Argument[0]", "sql-injection", "manual"] + - ["database/sql", "DB", True, "QueryRowContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["database/sql", "Tx", True, "Exec", "", "", "Argument[0]", "sql-injection", "manual"] + - ["database/sql", "Tx", True, "ExecContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["database/sql", "Tx", True, "Prepare", "", "", "Argument[0]", "sql-injection", "manual"] + - ["database/sql", "Tx", True, "PrepareContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["database/sql", "Tx", True, "Query", "", "", "Argument[0]", "sql-injection", "manual"] + - ["database/sql", "Tx", True, "QueryContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["database/sql", "Tx", True, "QueryRow", "", "", "Argument[0]", "sql-injection", "manual"] + - ["database/sql", "Tx", True, "QueryRowContext", "", "", "Argument[1]", "sql-injection", "manual"] - addsTo: pack: codeql/go-all extensible: summaryModel diff --git a/go/ql/lib/ext/fmt.model.yml b/go/ql/lib/ext/fmt.model.yml index cad64ce0fdf6..2baac68da3a0 100644 --- a/go/ql/lib/ext/fmt.model.yml +++ b/go/ql/lib/ext/fmt.model.yml @@ -1,4 +1,11 @@ extensions: + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["fmt", "", False, "Print", "", "", "Argument[0]", "log-injection", "manual"] + - ["fmt", "", False, "Printf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["fmt", "", False, "Println", "", "", "Argument[0]", "log-injection", "manual"] - addsTo: pack: codeql/go-all extensible: summaryModel diff --git a/go/ql/lib/ext/github.com.beego.beego.client.orm.model.yml b/go/ql/lib/ext/github.com.beego.beego.client.orm.model.yml new file mode 100644 index 000000000000..08c0572b894a --- /dev/null +++ b/go/ql/lib/ext/github.com.beego.beego.client.orm.model.yml @@ -0,0 +1,42 @@ +extensions: + - addsTo: + pack: codeql/go-all + extensible: packageGrouping + data: + - ["beego-orm", "github.com/beego/beego/client/orm"] + - ["beego-orm", "github.com/astaxie/beego/orm"] + - ["beego-orm", "github.com/beego/beego/orm"] + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["group:beego-orm", "Condition", True, "Raw", "", "", "Argument[1]", "sql-injection", "manual"] + - ["group:beego-orm", "DB", True, "Exec", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:beego-orm", "DB", True, "ExecContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["group:beego-orm", "DB", True, "Prepare", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:beego-orm", "DB", True, "PrepareContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["group:beego-orm", "DB", True, "Query", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:beego-orm", "DB", True, "QueryContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["group:beego-orm", "DB", True, "QueryRow", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:beego-orm", "DB", True, "QueryRowContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["group:beego-orm", "Ormer", True, "Raw", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:beego-orm", "QueryBuilder", True, "And", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:beego-orm", "QueryBuilder", True, "Delete", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:beego-orm", "QueryBuilder", True, "From", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:beego-orm", "QueryBuilder", True, "GroupBy", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:beego-orm", "QueryBuilder", True, "Having", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:beego-orm", "QueryBuilder", True, "In", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:beego-orm", "QueryBuilder", True, "InnerJoin", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:beego-orm", "QueryBuilder", True, "InsertInto", "", "", "Argument[0..1]", "sql-injection", "manual"] + - ["group:beego-orm", "QueryBuilder", True, "LeftJoin", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:beego-orm", "QueryBuilder", True, "On", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:beego-orm", "QueryBuilder", True, "Or", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:beego-orm", "QueryBuilder", True, "OrderBy", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:beego-orm", "QueryBuilder", True, "RightJoin", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:beego-orm", "QueryBuilder", True, "Select", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:beego-orm", "QueryBuilder", True, "Set", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:beego-orm", "QueryBuilder", True, "Subquery", "", "", "Argument[0..1]", "sql-injection", "manual"] + - ["group:beego-orm", "QueryBuilder", True, "Update", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:beego-orm", "QueryBuilder", True, "Values", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:beego-orm", "QueryBuilder", True, "Where", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:beego-orm", "QuerySeter", True, "FilterRaw", "", "", "Argument[1]", "sql-injection", "manual"] diff --git a/go/ql/lib/ext/github.com.beego.beego.core.logs.model.yml b/go/ql/lib/ext/github.com.beego.beego.core.logs.model.yml new file mode 100644 index 000000000000..b55c3be507dd --- /dev/null +++ b/go/ql/lib/ext/github.com.beego.beego.core.logs.model.yml @@ -0,0 +1,34 @@ +extensions: + - addsTo: + pack: codeql/go-all + extensible: packageGrouping + data: + - ["beego-logs", "github.com/astaxie/beego/logs"] + - ["beego-logs", "github.com/beego/beego/logs"] + - ["beego-logs", "github.com/beego/beego/core/logs"] + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["group:beego-logs", "", False, "Alert", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego-logs", "", False, "Critical", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego-logs", "", False, "Debug", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego-logs", "", False, "Emergency", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego-logs", "", False, "Error", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego-logs", "", False, "Info", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego-logs", "", False, "Informational", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego-logs", "", False, "Notice", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego-logs", "", False, "Trace", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego-logs", "", False, "Warn", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego-logs", "", False, "Warning", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego-logs", "BeeLogger", True, "Alert", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego-logs", "BeeLogger", True, "Critical", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego-logs", "BeeLogger", True, "Debug", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego-logs", "BeeLogger", True, "Emergency", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego-logs", "BeeLogger", True, "Error", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego-logs", "BeeLogger", True, "Info", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego-logs", "BeeLogger", True, "Informational", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego-logs", "BeeLogger", True, "Notice", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego-logs", "BeeLogger", True, "Trace", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego-logs", "BeeLogger", True, "Warn", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego-logs", "BeeLogger", True, "Warning", "", "", "Argument[0..1]", "log-injection", "manual"] diff --git a/go/ql/lib/ext/github.com.beego.beego.core.utils.model.yml b/go/ql/lib/ext/github.com.beego.beego.core.utils.model.yml index 4eb0688e37e7..63c05b920401 100644 --- a/go/ql/lib/ext/github.com.beego.beego.core.utils.model.yml +++ b/go/ql/lib/ext/github.com.beego.beego.core.utils.model.yml @@ -6,6 +6,11 @@ extensions: - ["beego-utils", "github.com/astaxie/beego/utils"] - ["beego-utils", "github.com/beego/beego/utils"] - ["beego-utils", "github.com/beego/beego/core/utils"] + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["group:beego-utils", "", False, "Display", "", "", "Argument[0]", "log-injection", "manual"] - addsTo: pack: codeql/go-all extensible: summaryModel diff --git a/go/ql/lib/ext/github.com.beego.beego.server.web.model.yml b/go/ql/lib/ext/github.com.beego.beego.server.web.model.yml index 963000fffccd..0c539522c5a7 100644 --- a/go/ql/lib/ext/github.com.beego.beego.server.web.model.yml +++ b/go/ql/lib/ext/github.com.beego.beego.server.web.model.yml @@ -10,6 +10,18 @@ extensions: pack: codeql/go-all extensible: sinkModel data: + # log-injection + - ["group:beego", "", False, "Alert", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego", "", False, "Critical", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego", "", False, "Debug", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego", "", False, "Emergency", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego", "", False, "Error", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego", "", False, "Info", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego", "", False, "Informational", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego", "", False, "Notice", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego", "", False, "Trace", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego", "", False, "Warn", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego", "", False, "Warning", "", "", "Argument[0..1]", "log-injection", "manual"] # path-injection - ["group:beego", "", False, "Walk", "", "", "Argument[1]", "path-injection", "manual"] - ["group:beego", "Controller", True, "SaveToFile", "", "", "Argument[1]", "path-injection", "manual"] diff --git a/go/ql/lib/ext/github.com.couchbase.gocb.model.yml b/go/ql/lib/ext/github.com.couchbase.gocb.model.yml index ff0a4c22c8de..d17b53dd6da9 100644 --- a/go/ql/lib/ext/github.com.couchbase.gocb.model.yml +++ b/go/ql/lib/ext/github.com.couchbase.gocb.model.yml @@ -3,28 +3,43 @@ extensions: pack: codeql/go-all extensible: packageGrouping data: - - ["gocb", "github.com/couchbase/gocb"] - - ["gocb", "gopkg.in/couchbase/gocb"] - - ["gocb", "github.com/couchbaselabs/gocb"] + - ["gocb1", "fixed-version:github.com/couchbase/gocb"] + - ["gocb1", "fixed-version:gopkg.in/couchbase/gocb.v1"] + - ["gocb1", "fixed-version:github.com/couchbaselabs/gocb"] + - ["gocb2", "github.com/couchbase/gocb/v2"] + - ["gocb2", "gopkg.in/couchbase/gocb.v2"] + - ["gocb2", "github.com/couchbaselabs/gocb/v2"] + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["group:gocb1", "Bucket", True, "ExecuteN1qlQuery", "", "", "Argument[0]", "nosql-injection", "manual"] + - ["group:gocb1", "Bucket", True, "ExecuteAnalyticsQuery", "", "", "Argument[0]", "nosql-injection", "manual"] + - ["group:gocb1", "Cluster", True, "ExecuteN1qlQuery", "", "", "Argument[0]", "nosql-injection", "manual"] + - ["group:gocb1", "Cluster", True, "ExecuteAnalyticsQuery", "", "", "Argument[0]", "nosql-injection", "manual"] + - ["group:gocb2", "Cluster", True, "AnalyticsQuery", "", "", "Argument[0]", "nosql-injection", "manual"] + - ["group:gocb2", "Cluster", True, "Query", "", "", "Argument[0]", "nosql-injection", "manual"] + - ["group:gocb2", "Scope", True, "AnalyticsQuery", "", "", "Argument[0]", "nosql-injection", "manual"] + - ["group:gocb2", "Scope", True, "Query", "", "", "Argument[0]", "nosql-injection", "manual"] - addsTo: pack: codeql/go-all extensible: summaryModel data: - - ["group:gocb", "", False, "NewAnalyticsQuery", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] - - ["group:gocb", "", False, "NewN1qlQuery", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] - - ["group:gocb", "AnalyticsQuery", True, "ContextId", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] - - ["group:gocb", "AnalyticsQuery", True, "Deferred", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] - - ["group:gocb", "AnalyticsQuery", True, "Pretty", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] - - ["group:gocb", "AnalyticsQuery", True, "Priority", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] - - ["group:gocb", "AnalyticsQuery", True, "RawParam", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] - - ["group:gocb", "AnalyticsQuery", True, "ServerSideTimeout", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] - - ["group:gocb", "N1qlQuery", True, "AdHoc", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] - - ["group:gocb", "N1qlQuery", True, "Consistency", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] - - ["group:gocb", "N1qlQuery", True, "ConsistentWith", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] - - ["group:gocb", "N1qlQuery", True, "Custom", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] - - ["group:gocb", "N1qlQuery", True, "PipelineBatch", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] - - ["group:gocb", "N1qlQuery", True, "PipelineCap", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] - - ["group:gocb", "N1qlQuery", True, "Profile", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] - - ["group:gocb", "N1qlQuery", True, "ReadOnly", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] - - ["group:gocb", "N1qlQuery", True, "ScanCap", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] - - ["group:gocb", "N1qlQuery", True, "Timeout", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] + - ["group:gocb1", "", False, "NewAnalyticsQuery", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["group:gocb1", "", False, "NewN1qlQuery", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["group:gocb1", "AnalyticsQuery", True, "ContextId", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] + - ["group:gocb1", "AnalyticsQuery", True, "Deferred", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] + - ["group:gocb1", "AnalyticsQuery", True, "Pretty", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] + - ["group:gocb1", "AnalyticsQuery", True, "Priority", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] + - ["group:gocb1", "AnalyticsQuery", True, "RawParam", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] + - ["group:gocb1", "AnalyticsQuery", True, "ServerSideTimeout", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] + - ["group:gocb1", "N1qlQuery", True, "AdHoc", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] + - ["group:gocb1", "N1qlQuery", True, "Consistency", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] + - ["group:gocb1", "N1qlQuery", True, "ConsistentWith", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] + - ["group:gocb1", "N1qlQuery", True, "Custom", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] + - ["group:gocb1", "N1qlQuery", True, "PipelineBatch", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] + - ["group:gocb1", "N1qlQuery", True, "PipelineCap", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] + - ["group:gocb1", "N1qlQuery", True, "Profile", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] + - ["group:gocb1", "N1qlQuery", True, "ReadOnly", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] + - ["group:gocb1", "N1qlQuery", True, "ScanCap", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] + - ["group:gocb1", "N1qlQuery", True, "Timeout", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] diff --git a/go/ql/lib/ext/github.com.davecgh.go-spew.spew.model.yml b/go/ql/lib/ext/github.com.davecgh.go-spew.spew.model.yml new file mode 100644 index 000000000000..4b4996926e31 --- /dev/null +++ b/go/ql/lib/ext/github.com.davecgh.go-spew.spew.model.yml @@ -0,0 +1,14 @@ +extensions: + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["github.com/davecgh/go-spew/spew", "", False, "Dump", "", "", "Argument[0]", "log-injection", "manual"] + - ["github.com/davecgh/go-spew/spew", "", False, "Errorf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["github.com/davecgh/go-spew/spew", "", False, "Fdump", "", "", "Argument[1]", "log-injection", "manual"] + - ["github.com/davecgh/go-spew/spew", "", False, "Fprint", "", "", "Argument[1]", "log-injection", "manual"] + - ["github.com/davecgh/go-spew/spew", "", False, "Fprintf", "", "", "Argument[1..2]", "log-injection", "manual"] + - ["github.com/davecgh/go-spew/spew", "", False, "Fprintln", "", "", "Argument[1]", "log-injection", "manual"] + - ["github.com/davecgh/go-spew/spew", "", False, "Print", "", "", "Argument[0]", "log-injection", "manual"] + - ["github.com/davecgh/go-spew/spew", "", False, "Printf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["github.com/davecgh/go-spew/spew", "", False, "Println", "", "", "Argument[0]", "log-injection", "manual"] diff --git a/go/ql/lib/ext/github.com.elazarl.goproxy.model.yml b/go/ql/lib/ext/github.com.elazarl.goproxy.model.yml index 20e4a26f1cdb..9dc8284ea58f 100644 --- a/go/ql/lib/ext/github.com.elazarl.goproxy.model.yml +++ b/go/ql/lib/ext/github.com.elazarl.goproxy.model.yml @@ -1,4 +1,10 @@ extensions: + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["github.com/elazarl/goproxy", "ProxyCtx", True, "Logf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["github.com/elazarl/goproxy", "ProxyCtx", True, "Warnf", "", "", "Argument[0..1]", "log-injection", "manual"] - addsTo: pack: codeql/go-all extensible: summaryModel diff --git a/go/ql/lib/ext/github.com.gogf.gf.database.gdb.model.yml b/go/ql/lib/ext/github.com.gogf.gf.database.gdb.model.yml new file mode 100644 index 000000000000..030656c6eb8a --- /dev/null +++ b/go/ql/lib/ext/github.com.gogf.gf.database.gdb.model.yml @@ -0,0 +1,57 @@ +extensions: + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + # These models are for v1. Some of them hold for v2, but we should model v2 properly. + - ["github.com/gogf/gf/database/gdb", "Core", True, "DoCommit", "", "", "Argument[2]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Core", True, "DoExec", "", "", "Argument[2]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Core", True, "DoGetAll", "", "", "Argument[2]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Core", True, "DoQuery", "", "", "Argument[2]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Core", True, "DoPrepare", "", "", "Argument[2]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Core", True, "Exec", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Core", True, "GetAll", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Core", True, "GetArray", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Core", True, "GetCount", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Core", True, "GetOne", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Core", True, "GetScan", "", "", "Argument[1]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Core", True, "GetStruct", "", "", "Argument[1]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Core", True, "GetStructs", "", "", "Argument[1]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Core", True, "GetValue", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Core", True, "Prepare", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Core", True, "Query", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Core", True, "Raw", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "DB", True, "DoCommit", "", "", "Argument[2]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "DB", True, "DoExec", "", "", "Argument[2]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "DB", True, "DoGetAll", "", "", "Argument[2]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "DB", True, "DoQuery", "", "", "Argument[2]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "DB", True, "DoPrepare", "", "", "Argument[2]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "DB", True, "Exec", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "DB", True, "GetAll", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "DB", True, "GetArray", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "DB", True, "GetCount", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "DB", True, "GetOne", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "DB", True, "GetScan", "", "", "Argument[1]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "DB", True, "GetStruct", "", "", "Argument[1]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "DB", True, "GetStructs", "", "", "Argument[1]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "DB", True, "GetValue", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "DB", True, "Prepare", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "DB", True, "Query", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "DB", True, "Raw", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Tx", True, "DoCommit", "", "", "Argument[2]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Tx", True, "DoExec", "", "", "Argument[2]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Tx", True, "DoGetAll", "", "", "Argument[2]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Tx", True, "DoQuery", "", "", "Argument[2]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Tx", True, "DoPrepare", "", "", "Argument[2]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Tx", True, "Exec", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Tx", True, "GetAll", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Tx", True, "GetArray", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Tx", True, "GetCount", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Tx", True, "GetOne", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Tx", True, "GetScan", "", "", "Argument[1]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Tx", True, "GetStruct", "", "", "Argument[1]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Tx", True, "GetStructs", "", "", "Argument[1]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Tx", True, "GetValue", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Tx", True, "Prepare", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Tx", True, "Query", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Tx", True, "Raw", "", "", "Argument[0]", "sql-injection", "manual"] diff --git a/go/ql/lib/ext/github.com.golang.glog.model.yml b/go/ql/lib/ext/github.com.golang.glog.model.yml new file mode 100644 index 000000000000..275450f2c447 --- /dev/null +++ b/go/ql/lib/ext/github.com.golang.glog.model.yml @@ -0,0 +1,102 @@ +extensions: + - addsTo: + pack: codeql/go-all + extensible: packageGrouping + data: + - ["glog", "github.com/golang/glog"] + - ["glog", "gopkg.in/glog"] + - ["glog", "k8s.io/klog"] + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["group:glog", "", False, "Error", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:glog", "", False, "ErrorContext", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:glog", "", False, "ErrorContextDepth", "", "", "Argument[2]", "log-injection", "manual"] + - ["group:glog", "", False, "ErrorContextDepthf", "", "", "Argument[2..3]", "log-injection", "manual"] + - ["group:glog", "", False, "ErrorContextf", "", "", "Argument[1..2]", "log-injection", "manual"] + - ["group:glog", "", False, "ErrorDepth", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:glog", "", False, "ErrorDepthf", "", "", "Argument[1..2]", "log-injection", "manual"] + - ["group:glog", "", False, "Errorf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:glog", "", False, "Errorln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:glog", "", False, "Exit", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:glog", "", False, "ExitContext", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:glog", "", False, "ExitContextDepth", "", "", "Argument[2]", "log-injection", "manual"] + - ["group:glog", "", False, "ExitContextDepthf", "", "", "Argument[2..3]", "log-injection", "manual"] + - ["group:glog", "", False, "ExitContextf", "", "", "Argument[1..2]", "log-injection", "manual"] + - ["group:glog", "", False, "ExitDepth", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:glog", "", False, "ExitDepthf", "", "", "Argument[1..2]", "log-injection", "manual"] + - ["group:glog", "", False, "Exitf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:glog", "", False, "Exitln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:glog", "", False, "Fatal", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:glog", "", False, "FatalContext", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:glog", "", False, "FatalContextDepth", "", "", "Argument[2]", "log-injection", "manual"] + - ["group:glog", "", False, "FatalContextDepthf", "", "", "Argument[2..3]", "log-injection", "manual"] + - ["group:glog", "", False, "FatalContextf", "", "", "Argument[1..2]", "log-injection", "manual"] + - ["group:glog", "", False, "FatalDepth", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:glog", "", False, "FatalDepthf", "", "", "Argument[1..2]", "log-injection", "manual"] + - ["group:glog", "", False, "Fatalf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:glog", "", False, "Fatalln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:glog", "", False, "Info", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:glog", "", False, "InfoContext", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:glog", "", False, "InfoContextDepth", "", "", "Argument[2]", "log-injection", "manual"] + - ["group:glog", "", False, "InfoContextDepthf", "", "", "Argument[2..3]", "log-injection", "manual"] + - ["group:glog", "", False, "InfoContextf", "", "", "Argument[1..2]", "log-injection", "manual"] + - ["group:glog", "", False, "InfoDepth", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:glog", "", False, "InfoDepthf", "", "", "Argument[1..2]", "log-injection", "manual"] + - ["group:glog", "", False, "Infof", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:glog", "", False, "Infoln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:glog", "", False, "Warning", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:glog", "", False, "WarningContext", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:glog", "", False, "WarningContextDepth", "", "", "Argument[2]", "log-injection", "manual"] + - ["group:glog", "", False, "WarningContextDepthf", "", "", "Argument[2..3]", "log-injection", "manual"] + - ["group:glog", "", False, "WarningContextf", "", "", "Argument[1..2]", "log-injection", "manual"] + - ["group:glog", "", False, "WarningDepth", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:glog", "", False, "WarningDepthf", "", "", "Argument[1..2]", "log-injection", "manual"] + - ["group:glog", "", False, "Warningf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:glog", "", False, "Warningln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "Error", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "ErrorContext", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "ErrorContextDepth", "", "", "Argument[2]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "ErrorContextDepthf", "", "", "Argument[2..3]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "ErrorContextf", "", "", "Argument[1..2]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "ErrorDepth", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "ErrorDepthf", "", "", "Argument[1..2]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "Errorf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "Errorln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "Exit", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "ExitContext", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "ExitContextDepth", "", "", "Argument[2]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "ExitContextDepthf", "", "", "Argument[2..3]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "ExitContextf", "", "", "Argument[1..2]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "ExitDepth", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "ExitDepthf", "", "", "Argument[1..2]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "Exitf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "Exitln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "Fatal", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "FatalContext", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "FatalContextDepth", "", "", "Argument[2]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "FatalContextDepthf", "", "", "Argument[2..3]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "FatalContextf", "", "", "Argument[1..2]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "FatalDepth", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "FatalDepthf", "", "", "Argument[1..2]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "Fatalf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "Fatalln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "Info", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "InfoContext", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "InfoContextDepth", "", "", "Argument[2]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "InfoContextDepthf", "", "", "Argument[2..3]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "InfoContextf", "", "", "Argument[1..2]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "InfoDepth", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "InfoDepthf", "", "", "Argument[1..2]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "Infof", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "Infoln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "Warning", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "WarningContext", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "WarningContextDepth", "", "", "Argument[2]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "WarningContextDepthf", "", "", "Argument[2..3]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "WarningContextf", "", "", "Argument[1..2]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "WarningDepth", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "WarningDepthf", "", "", "Argument[1..2]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "Warningf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "Warningln", "", "", "Argument[0]", "log-injection", "manual"] diff --git a/go/ql/lib/ext/github.com.jmoiron.sqlx.model.yml b/go/ql/lib/ext/github.com.jmoiron.sqlx.model.yml new file mode 100644 index 000000000000..8c9d19b4b85b --- /dev/null +++ b/go/ql/lib/ext/github.com.jmoiron.sqlx.model.yml @@ -0,0 +1,17 @@ +extensions: + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["github.com/jmoiron/sqlx", "DB", True, "Get", "", "", "Argument[1]", "sql-injection", "manual"] + - ["github.com/jmoiron/sqlx", "DB", True, "MustExec", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/jmoiron/sqlx", "DB", True, "NamedExec", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/jmoiron/sqlx", "DB", True, "NamedQuery", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/jmoiron/sqlx", "DB", True, "Queryx", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/jmoiron/sqlx", "DB", True, "Select", "", "", "Argument[1]", "sql-injection", "manual"] + - ["github.com/jmoiron/sqlx", "Tx", True, "Get", "", "", "Argument[1]", "sql-injection", "manual"] + - ["github.com/jmoiron/sqlx", "Tx", True, "MustExec", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/jmoiron/sqlx", "Tx", True, "NamedExec", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/jmoiron/sqlx", "Tx", True, "NamedQuery", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/jmoiron/sqlx", "Tx", True, "Queryx", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/jmoiron/sqlx", "Tx", True, "Select", "", "", "Argument[1]", "sql-injection", "manual"] diff --git a/go/ql/lib/ext/github.com.mastermind.squirrel.model.yml b/go/ql/lib/ext/github.com.mastermind.squirrel.model.yml new file mode 100644 index 000000000000..6f3c5830e457 --- /dev/null +++ b/go/ql/lib/ext/github.com.mastermind.squirrel.model.yml @@ -0,0 +1,51 @@ +extensions: + - addsTo: + pack: codeql/go-all + extensible: packageGrouping + data: + - ["squirrel", "github.com/Masterminds/squirrel"] + - ["squirrel", "gopkg.in/Masterminds/squirrel"] + - ["squirrel", "github.com/lann/squirrel"] + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["group:squirrel", "", False, "Delete", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:squirrel", "", False, "Expr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:squirrel", "", False, "Insert", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:squirrel", "", False, "Select", "", "", "Argument[0]", "sql-injection", "manual"] # TODO: when sources can have access paths, use .ArrayElement + - ["group:squirrel", "", False, "Update", "", "", "Argument[0]", "sql-injection", "manual"] # TODO: when sources can have access paths, use .ArrayElement + + - ["group:squirrel", "DeleteBuilder", True, "From", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:squirrel", "DeleteBuilder", True, "OrderBy", "", "", "Argument[0]", "sql-injection", "manual"] # TODO: when sources can have access paths, use .ArrayElement + - ["group:squirrel", "DeleteBuilder", True, "Prefix", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:squirrel", "DeleteBuilder", True, "Suffix", "", "", "Argument[0]", "sql-injection", "manual"] + # DeleteBuilder.Where has to be modeled in QL to avoid FPs when a non-string argument is used + + - ["group:squirrel", "InsertBuilder", True, "Columns", "", "", "Argument[0]", "sql-injection", "manual"] # TODO: when sources can have access paths, use .ArrayElement + - ["group:squirrel", "InsertBuilder", True, "Into", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:squirrel", "InsertBuilder", True, "Options", "", "", "Argument[0]", "sql-injection", "manual"] # TODO: when sources can have access paths, use .ArrayElement + - ["group:squirrel", "InsertBuilder", True, "Prefix", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:squirrel", "InsertBuilder", True, "Suffix", "", "", "Argument[0]", "sql-injection", "manual"] + + - ["group:squirrel", "SelectBuilder", True, "CrossJoin", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:squirrel", "SelectBuilder", True, "Column", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:squirrel", "SelectBuilder", True, "Columns", "", "", "Argument[0]", "sql-injection", "manual"] # TODO: when sources can have access paths, use .ArrayElement + - ["group:squirrel", "SelectBuilder", True, "From", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:squirrel", "SelectBuilder", True, "GroupBy", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:squirrel", "SelectBuilder", True, "InnerJoin", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:squirrel", "SelectBuilder", True, "LeftJoin", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:squirrel", "SelectBuilder", True, "Options", "", "", "Argument[0]", "sql-injection", "manual"] # TODO: when sources can have access paths, use .ArrayElement + - ["group:squirrel", "SelectBuilder", True, "OrderBy", "", "", "Argument[0]", "sql-injection", "manual"] # TODO: when sources can have access paths, use .ArrayElement + - ["group:squirrel", "SelectBuilder", True, "Prefix", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:squirrel", "SelectBuilder", True, "RightJoin", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:squirrel", "SelectBuilder", True, "Suffix", "", "", "Argument[0]", "sql-injection", "manual"] + # SelectBuilder.Where has to be modeled in QL to avoid FPs when a non-string argument is used + + - ["group:squirrel", "UpdateBuilder", True, "From", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:squirrel", "UpdateBuilder", True, "OrderBy", "", "", "Argument[0]", "sql-injection", "manual"] # TODO: when sources can have access paths, use .ArrayElement + - ["group:squirrel", "UpdateBuilder", True, "Prefix", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:squirrel", "UpdateBuilder", True, "Set", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:squirrel", "UpdateBuilder", True, "Suffix", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:squirrel", "UpdateBuilder", True, "Table", "", "", "Argument[0]", "sql-injection", "manual"] + # UpdateBuilder.Where has to be modeled in QL to avoid FPs when a non-string argument is used diff --git a/go/ql/lib/ext/github.com.rqlite.gorqlite.model.yml b/go/ql/lib/ext/github.com.rqlite.gorqlite.model.yml new file mode 100644 index 000000000000..62e24f2c920b --- /dev/null +++ b/go/ql/lib/ext/github.com.rqlite.gorqlite.model.yml @@ -0,0 +1,35 @@ +extensions: + - addsTo: + pack: codeql/go-all + extensible: packageGrouping + data: + - ["gorqlite", "github.com/rqlite/gorqlite"] + - ["gorqlite", "github.com/raindog308/gorqlite"] + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["group:gorqlite", "Connection", True, "Query", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:gorqlite", "Connection", True, "QueryContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["group:gorqlite", "Connection", True, "QueryOne", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:gorqlite", "Connection", True, "QueryOneContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["group:gorqlite", "Connection", True, "QueryOneParameterized", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:gorqlite", "Connection", True, "QueryOneParameterizedContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["group:gorqlite", "Connection", True, "QueryParameterized", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:gorqlite", "Connection", True, "QueryParameterizedContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["group:gorqlite", "Connection", True, "Queue", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:gorqlite", "Connection", True, "QueueContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["group:gorqlite", "Connection", True, "QueueOne", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:gorqlite", "Connection", True, "QueueOneContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["group:gorqlite", "Connection", True, "QueueOneParameterized", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:gorqlite", "Connection", True, "QueueOneParameterizedContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["group:gorqlite", "Connection", True, "QueueParameterized", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:gorqlite", "Connection", True, "QueueParameterizedContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["group:gorqlite", "Connection", True, "Write", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:gorqlite", "Connection", True, "WriteContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["group:gorqlite", "Connection", True, "WriteOne", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:gorqlite", "Connection", True, "WriteOneContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["group:gorqlite", "Connection", True, "WriteOneParameterized", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:gorqlite", "Connection", True, "WriteOneParameterizedContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["group:gorqlite", "Connection", True, "WriteParameterized", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:gorqlite", "Connection", True, "WriteParameterizedContext", "", "", "Argument[1]", "sql-injection", "manual"] diff --git a/go/ql/lib/ext/github.com.sirupsen.logrus.model.yml b/go/ql/lib/ext/github.com.sirupsen.logrus.model.yml new file mode 100644 index 000000000000..06f9a54622b4 --- /dev/null +++ b/go/ql/lib/ext/github.com.sirupsen.logrus.model.yml @@ -0,0 +1,159 @@ +extensions: + - addsTo: + pack: codeql/go-all + extensible: packageGrouping + data: + - ["logrus", "github.com/sirupsen/logrus"] + - ["logrus", "github.com/Sirupsen/logrus"] + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["group:logrus", "", False, "Debug", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "DebugFn", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "Debugf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "", False, "Debugln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "Error", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "ErrorFn", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "Errorf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "", False, "Errorln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "Fatal", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "FatalFn", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "Fatalf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "", False, "Fatalln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "Info", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "InfoFn", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "Infof", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "", False, "Infoln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "Panic", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "PanicFn", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "Panicf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "", False, "Panicln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "Print", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "PrintFn", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "Printf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "", False, "Println", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "Trace", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "TraceFn", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "Tracef", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "", False, "Traceln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "Warn", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "WarnFn", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "Warnf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "", False, "Warnln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "Warning", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "WarningFn", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "Warningf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "", False, "Warningln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "WithError", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "WithField", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "", False, "WithFields", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "WithTime", "", "", "Argument[0]", "log-injection", "manual"] + + - ["group:logrus", "Entry", True, "Debug", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Debugf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Debugln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Error", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Errorf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Errorln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Fatal", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Fatalf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Fatalln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Info", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Infof", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Infoln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Log", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Logf", "", "", "Argument[1..2]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Logln", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Panic", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Panicf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Panicln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Print", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Printf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Println", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Trace", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Tracef", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Traceln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Warn", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Warnf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Warnln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Warning", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Warningf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Warningln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "WithError", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "WithField", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "WithFields", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "WithTime", "", "", "Argument[0]", "log-injection", "manual"] + + - ["group:logrus", "FieldLogger", True, "Debug", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "Debugf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "Debugln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "Error", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "Errorf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "Errorln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "Fatal", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "Fatalf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "Fatalln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "Info", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "Infof", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "Infoln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "Panic", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "Panicf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "Panicln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "Print", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "Printf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "Println", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "Warn", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "Warnf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "Warnln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "Warning", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "Warningf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "Warningln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "WithError", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "WithField", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "WithFields", "", "", "Argument[0]", "log-injection", "manual"] + + - ["group:logrus", "Logger", True, "Debug", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "DebugFn", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Debugf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Debugln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Error", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "ErrorFn", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Errorf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Errorln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Fatal", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "FatalFn", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Fatalf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Fatalln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Info", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "InfoFn", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Infof", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Infoln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Log", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "LogFn", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Logf", "", "", "Argument[1..2]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Logln", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Panic", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "PanicFn", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Panicf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Panicln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Print", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "PrintFn", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Printf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Println", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Trace", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "TraceFn", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Tracef", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Traceln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Warn", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "WarnFn", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Warnf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Warnln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Warning", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "WarningFn", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Warningf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Warningln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "WithError", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "WithField", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "WithFields", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "WithTime", "", "", "Argument[0]", "log-injection", "manual"] diff --git a/go/ql/lib/ext/github.com.uptrace.bun.model.yml b/go/ql/lib/ext/github.com.uptrace.bun.model.yml new file mode 100644 index 000000000000..a08adb07973d --- /dev/null +++ b/go/ql/lib/ext/github.com.uptrace.bun.model.yml @@ -0,0 +1,68 @@ +extensions: + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["github.com/uptrace/bun", "", False, "NewRawQuery", "", "", "Argument[1]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "AddColumnQuery", True, "ColumnExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "AddColumnQuery", True, "ModelTableExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "AddColumnQuery", True, "TableExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "Conn", True, "Exec", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "Conn", True, "ExecContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "Conn", True, "NewRaw", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "Conn", True, "Prepare", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "Conn", True, "Query", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "Conn", True, "QueryRow", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "Conn", True, "PrepareContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "Conn", True, "QueryContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "Conn", True, "QueryRowContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "Conn", True, "Raw", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "CreateIndexQuery", True, "ColumnExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "CreateIndexQuery", True, "ModelTableExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "CreateIndexQuery", True, "TableExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "CreateIndexQuery", True, "Where", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "CreateIndexQuery", True, "WhereOr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "CreateTableQuery", True, "ColumnExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "CreateTableQuery", True, "ModelTableExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "CreateTableQuery", True, "TableExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "DB", True, "Exec", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "DB", True, "ExecContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "DB", True, "NewRaw", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "DB", True, "Prepare", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "DB", True, "Query", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "DB", True, "QueryRow", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "DB", True, "PrepareContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "DB", True, "QueryContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "DB", True, "QueryRowContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "DB", True, "Raw", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "DeleteQuery", True, "TableExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "DeleteQuery", True, "Where", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "DeleteQuery", True, "WhereOr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "DropColumnQuery", True, "ColumnExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "DropColumnQuery", True, "ModelTableExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "DropColumnQuery", True, "TableExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "DropTableQuery", True, "ModelTableExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "DropTableQuery", True, "TableExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "InsertQuery", True, "ColumnExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "InsertQuery", True, "ModelTableExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "InsertQuery", True, "TableExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "InsertQuery", True, "Where", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "InsertQuery", True, "WhereOr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "MergeQuery", True, "ModelTableExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "MergeQuery", True, "TableExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "RawQuery", True, "NewRaw", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "SelectQuery", True, "ColumnExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "SelectQuery", True, "DistinctOn", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "SelectQuery", True, "For", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "SelectQuery", True, "GroupExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "SelectQuery", True, "Having", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "SelectQuery", True, "ModelTableExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "SelectQuery", True, "OrderExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "SelectQuery", True, "TableExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "SelectQuery", True, "Where", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "SelectQuery", True, "WhereOr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "TruncateTableQuery", True, "TableExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "UpdateQuery", True, "ModelTableExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "UpdateQuery", True, "TableExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "UpdateQuery", True, "Where", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "UpdateQuery", True, "WhereOr", "", "", "Argument[0]", "sql-injection", "manual"] diff --git a/go/ql/lib/ext/go.mongodb.org.mongo-driver.mongo.model.yml b/go/ql/lib/ext/go.mongodb.org.mongo-driver.mongo.model.yml new file mode 100644 index 000000000000..6c2d4afdeae2 --- /dev/null +++ b/go/ql/lib/ext/go.mongodb.org.mongo-driver.mongo.model.yml @@ -0,0 +1,19 @@ +extensions: + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["go.mongodb.org/mongo-driver/mongo", "Collection", True, "Aggregate", "", "", "Argument[1]", "nosql-injection", "manual"] + - ["go.mongodb.org/mongo-driver/mongo", "Collection", True, "CountDocuments", "", "", "Argument[1]", "nosql-injection", "manual"] + - ["go.mongodb.org/mongo-driver/mongo", "Collection", True, "DeleteMany", "", "", "Argument[1]", "nosql-injection", "manual"] + - ["go.mongodb.org/mongo-driver/mongo", "Collection", True, "DeleteOne", "", "", "Argument[1]", "nosql-injection", "manual"] + - ["go.mongodb.org/mongo-driver/mongo", "Collection", True, "Distinct", "", "", "Argument[2]", "nosql-injection", "manual"] + - ["go.mongodb.org/mongo-driver/mongo", "Collection", True, "Find", "", "", "Argument[1]", "nosql-injection", "manual"] + - ["go.mongodb.org/mongo-driver/mongo", "Collection", True, "FindOne", "", "", "Argument[1]", "nosql-injection", "manual"] + - ["go.mongodb.org/mongo-driver/mongo", "Collection", True, "FindOneAndDelete", "", "", "Argument[1]", "nosql-injection", "manual"] + - ["go.mongodb.org/mongo-driver/mongo", "Collection", True, "FindOneAndReplace", "", "", "Argument[1]", "nosql-injection", "manual"] + - ["go.mongodb.org/mongo-driver/mongo", "Collection", True, "FindOneAndUpdate", "", "", "Argument[1]", "nosql-injection", "manual"] + - ["go.mongodb.org/mongo-driver/mongo", "Collection", True, "ReplaceOne", "", "", "Argument[1]", "nosql-injection", "manual"] + - ["go.mongodb.org/mongo-driver/mongo", "Collection", True, "UpdateMany", "", "", "Argument[1]", "nosql-injection", "manual"] + - ["go.mongodb.org/mongo-driver/mongo", "Collection", True, "UpdateOne", "", "", "Argument[1]", "nosql-injection", "manual"] + - ["go.mongodb.org/mongo-driver/mongo", "Collection", True, "Watch", "", "", "Argument[1]", "nosql-injection", "manual"] diff --git a/go/ql/lib/ext/go.uber.org.zap.model.yml b/go/ql/lib/ext/go.uber.org.zap.model.yml index 2ca7f7e8a804..e9fc971e5fa2 100644 --- a/go/ql/lib/ext/go.uber.org.zap.model.yml +++ b/go/ql/lib/ext/go.uber.org.zap.model.yml @@ -1,4 +1,41 @@ extensions: + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["go.uber.org/zap", "Logger", True, "DPanic", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["go.uber.org/zap", "Logger", True, "Debug", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["go.uber.org/zap", "Logger", True, "Error", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["go.uber.org/zap", "Logger", True, "Fatal", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["go.uber.org/zap", "Logger", True, "Info", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["go.uber.org/zap", "Logger", True, "Named", "", "", "Argument[0]", "log-injection", "manual"] + - ["go.uber.org/zap", "Logger", True, "Panic", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["go.uber.org/zap", "Logger", True, "Warn", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["go.uber.org/zap", "Logger", True, "With", "", "", "Argument[0]", "log-injection", "manual"] + - ["go.uber.org/zap", "Logger", True, "WithOptions", "", "", "Argument[0]", "log-injection", "manual"] + - ["go.uber.org/zap", "SugaredLogger", True, "DPanic", "", "", "Argument[0]", "log-injection", "manual"] + - ["go.uber.org/zap", "SugaredLogger", True, "DPanicf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["go.uber.org/zap", "SugaredLogger", True, "DPanicw", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["go.uber.org/zap", "SugaredLogger", True, "Debug", "", "", "Argument[0]", "log-injection", "manual"] + - ["go.uber.org/zap", "SugaredLogger", True, "Debugf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["go.uber.org/zap", "SugaredLogger", True, "Debugw", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["go.uber.org/zap", "SugaredLogger", True, "Error", "", "", "Argument[0]", "log-injection", "manual"] + - ["go.uber.org/zap", "SugaredLogger", True, "Errorf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["go.uber.org/zap", "SugaredLogger", True, "Errorw", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["go.uber.org/zap", "SugaredLogger", True, "Fatal", "", "", "Argument[0]", "log-injection", "manual"] + - ["go.uber.org/zap", "SugaredLogger", True, "Fatalf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["go.uber.org/zap", "SugaredLogger", True, "Fatalw", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["go.uber.org/zap", "SugaredLogger", True, "Info", "", "", "Argument[0]", "log-injection", "manual"] + - ["go.uber.org/zap", "SugaredLogger", True, "Infof", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["go.uber.org/zap", "SugaredLogger", True, "Infow", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["go.uber.org/zap", "SugaredLogger", True, "Named", "", "", "Argument[0]", "log-injection", "manual"] + - ["go.uber.org/zap", "SugaredLogger", True, "Panic", "", "", "Argument[0]", "log-injection", "manual"] + - ["go.uber.org/zap", "SugaredLogger", True, "Panicf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["go.uber.org/zap", "SugaredLogger", True, "Panicw", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["go.uber.org/zap", "SugaredLogger", True, "Warn", "", "", "Argument[0]", "log-injection", "manual"] + - ["go.uber.org/zap", "SugaredLogger", True, "Warnf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["go.uber.org/zap", "SugaredLogger", True, "Warnw", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["go.uber.org/zap", "SugaredLogger", True, "With", "", "", "Argument[0]", "log-injection", "manual"] - addsTo: pack: codeql/go-all extensible: summaryModel diff --git a/go/ql/lib/ext/gorm.io.gorm.model.yml b/go/ql/lib/ext/gorm.io.gorm.model.yml new file mode 100644 index 000000000000..bfcf1fa66a76 --- /dev/null +++ b/go/ql/lib/ext/gorm.io.gorm.model.yml @@ -0,0 +1,25 @@ +extensions: + - addsTo: + pack: codeql/go-all + extensible: packageGrouping + data: + - ["gorm", "gorm.io/gorm"] + - ["gorm", "github.com/jinzhu/gorm"] + - ["gorm", "github.com/go-gorm/gorm"] + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["group:gorm", "DB", True, "Where", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:gorm", "DB", True, "Raw", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:gorm", "DB", True, "Order", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:gorm", "DB", True, "Not", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:gorm", "DB", True, "Or", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:gorm", "DB", True, "Select", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:gorm", "DB", True, "Table", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:gorm", "DB", True, "Group", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:gorm", "DB", True, "Having", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:gorm", "DB", True, "Joins", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:gorm", "DB", True, "Exec", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:gorm", "DB", True, "Distinct", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:gorm", "DB", True, "Pluck", "", "", "Argument[0]", "sql-injection", "manual"] diff --git a/go/ql/lib/ext/log.model.yml b/go/ql/lib/ext/log.model.yml index 7f52a1733073..4d1df7cf0821 100644 --- a/go/ql/lib/ext/log.model.yml +++ b/go/ql/lib/ext/log.model.yml @@ -1,4 +1,28 @@ extensions: + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["log", "", False, "Fatal", "", "", "Argument[0]", "log-injection", "manual"] + - ["log", "", False, "Fatalf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["log", "", False, "Fatalln", "", "", "Argument[0]", "log-injection", "manual"] + - ["log", "", False, "Output", "", "", "Argument[1]", "log-injection", "manual"] + - ["log", "", False, "Panic", "", "", "Argument[0]", "log-injection", "manual"] + - ["log", "", False, "Panicf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["log", "", False, "Panicln", "", "", "Argument[0]", "log-injection", "manual"] + - ["log", "", False, "Print", "", "", "Argument[0]", "log-injection", "manual"] + - ["log", "", False, "Printf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["log", "", False, "Println", "", "", "Argument[0]", "log-injection", "manual"] + - ["log", "Logger", True, "Fatal", "", "", "Argument[0]", "log-injection", "manual"] + - ["log", "Logger", True, "Fatalf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["log", "Logger", True, "Fatalln", "", "", "Argument[0]", "log-injection", "manual"] + - ["log", "Logger", True, "Output", "", "", "Argument[1]", "log-injection", "manual"] + - ["log", "Logger", True, "Panic", "", "", "Argument[0]", "log-injection", "manual"] + - ["log", "Logger", True, "Panicf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["log", "Logger", True, "Panicln", "", "", "Argument[0]", "log-injection", "manual"] + - ["log", "Logger", True, "Print", "", "", "Argument[0]", "log-injection", "manual"] + - ["log", "Logger", True, "Printf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["log", "Logger", True, "Println", "", "", "Argument[0]", "log-injection", "manual"] - addsTo: pack: codeql/go-all extensible: summaryModel diff --git a/go/ql/lib/ext/xorm.io.xorm.model.yml b/go/ql/lib/ext/xorm.io.xorm.model.yml new file mode 100644 index 000000000000..5cf1ac4f5d73 --- /dev/null +++ b/go/ql/lib/ext/xorm.io.xorm.model.yml @@ -0,0 +1,49 @@ +extensions: + - addsTo: + pack: codeql/go-all + extensible: packageGrouping + data: + - ["xorm", "xorm.io/xorm"] + - ["xorm", "github.com/go-xorm/xorm"] + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["group:xorm", "Engine", True, "Alias", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:xorm", "Engine", True, "And", "", "", "Argument[0]", "sql-injection", "manual"] + # Engine.Exec has to be modeled in QL to select only the first syntactic argument + - ["group:xorm", "Engine", True, "GroupBy", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:xorm", "Engine", True, "Having", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:xorm", "Engine", True, "In", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:xorm", "Engine", True, "Join", "", "", "Argument[0..2]", "sql-injection", "manual"] + - ["group:xorm", "Engine", True, "NotIn", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:xorm", "Engine", True, "Or", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:xorm", "Engine", True, "OrderBy", "", "", "Argument[0]", "sql-injection", "manual"] + # Engine.Query, Engine.QueryInterface and Engine.QueryString have to be modeled in QL to select only the first syntactic argument + - ["group:xorm", "Engine", True, "Select", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:xorm", "Engine", True, "SetExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:xorm", "Engine", True, "SQL", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:xorm", "Engine", True, "Sum", "", "", "Argument[1]", "sql-injection", "manual"] + - ["group:xorm", "Engine", True, "Sums", "", "", "Argument[1]", "sql-injection", "manual"] + - ["group:xorm", "Engine", True, "SumInt", "", "", "Argument[1]", "sql-injection", "manual"] + - ["group:xorm", "Engine", True, "SumsInt", "", "", "Argument[1]", "sql-injection", "manual"] + - ["group:xorm", "Engine", True, "Where", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:xorm", "Session", True, "Alias", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:xorm", "Session", True, "And", "", "", "Argument[0]", "sql-injection", "manual"] + # Session.Exec has to be modeled in QL to select only the first syntactic argument + - ["group:xorm", "Session", True, "GroupBy", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:xorm", "Session", True, "Having", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:xorm", "Session", True, "In", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:xorm", "Session", True, "Join", "", "", "Argument[0..2]", "sql-injection", "manual"] + - ["group:xorm", "Session", True, "NotIn", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:xorm", "Session", True, "Or", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:xorm", "Session", True, "OrderBy", "", "", "Argument[0]", "sql-injection", "manual"] + # Session.Query, Session.QueryInterface and Session.QueryString have to be modeled in QL to select only the first syntactic argument + - ["group:xorm", "Session", True, "Select", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:xorm", "Session", True, "SetExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:xorm", "Session", True, "SQL", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:xorm", "Session", True, "Sum", "", "", "Argument[1]", "sql-injection", "manual"] + - ["group:xorm", "Session", True, "Sums", "", "", "Argument[1]", "sql-injection", "manual"] + - ["group:xorm", "Session", True, "SumInt", "", "", "Argument[1]", "sql-injection", "manual"] + - ["group:xorm", "Session", True, "SumsInt", "", "", "Argument[1]", "sql-injection", "manual"] + - ["group:xorm", "Session", True, "Where", "", "", "Argument[0]", "sql-injection", "manual"] diff --git a/go/ql/lib/semmle/go/Concepts.qll b/go/ql/lib/semmle/go/Concepts.qll index c15d3683b40c..3f0cd0f8885e 100644 --- a/go/ql/lib/semmle/go/Concepts.qll +++ b/go/ql/lib/semmle/go/Concepts.qll @@ -373,6 +373,48 @@ module LoggerCall { } } +private class DefaultLoggerCall extends LoggerCall::Range, DataFlow::CallNode { + DataFlow::ArgumentNode messageComponent; + + DefaultLoggerCall() { + sinkNode(messageComponent, "log-injection") and + this = messageComponent.getCall() + } + + override DataFlow::Node getAMessageComponent() { + not messageComponent instanceof DataFlow::ImplicitVarargsSlice and + result = messageComponent + or + messageComponent instanceof DataFlow::ImplicitVarargsSlice and + result = this.getAnImplicitVarargsArgument() + } +} + +/** + * A call to an interface that looks like a logger. It is common to use a + * locally-defined interface for logging to make it easy to changing logging + * library. + */ +private class HeuristicLoggerCall extends LoggerCall::Range, DataFlow::CallNode { + HeuristicLoggerCall() { + exists(Method m, string tp, string logFunctionPrefix, string name | + m = this.getTarget() and + m.hasQualifiedName(_, tp, name) and + m.getReceiverBaseType().getUnderlyingType() instanceof InterfaceType + | + tp.regexpMatch(".*[lL]ogger") and + logFunctionPrefix = + [ + "Debug", "Error", "Fatal", "Info", "Log", "Output", "Panic", "Print", "Trace", "Warn", + "With" + ] and + name.matches(logFunctionPrefix + "%") + ) + } + + override DataFlow::Node getAMessageComponent() { result = this.getASyntacticArgument() } +} + /** * A function that encodes data into a binary or textual format. * diff --git a/go/ql/lib/semmle/go/Scopes.qll b/go/ql/lib/semmle/go/Scopes.qll index f9b9e3a26b9a..c3671c74b5cd 100644 --- a/go/ql/lib/semmle/go/Scopes.qll +++ b/go/ql/lib/semmle/go/Scopes.qll @@ -472,7 +472,7 @@ class Function extends ValueEntity, @functionobject { /** Gets a parameter of this function. */ Parameter getAParameter() { result = this.getParameter(_) } - /** Gets the `i`th reslt variable of this function. */ + /** Gets the `i`th result variable of this function. */ ResultVariable getResult(int i) { result.isResultOf(this.getFuncDecl(), i) } /** Gets a result variable of this function. */ diff --git a/go/ql/lib/semmle/go/frameworks/Beego.qll b/go/ql/lib/semmle/go/frameworks/Beego.qll index 9f6ee5980035..a9e296a1f973 100644 --- a/go/ql/lib/semmle/go/frameworks/Beego.qll +++ b/go/ql/lib/semmle/go/frameworks/Beego.qll @@ -33,13 +33,6 @@ module Beego { result = package(v2modulePath(), "server/web/context") } - /** Gets the path for the logs package of beego. */ - string logsPackagePath() { - result = package(v1modulePath(), "logs") - or - result = package(v2modulePath(), "core/logs") - } - /** Gets the path for the utils package of beego. */ string utilsPackagePath() { result = package(v1modulePath(), "utils") @@ -172,36 +165,6 @@ module Beego { override string getAContentType() { none() } } - private string getALogFunctionName() { - result = - [ - "Alert", "Critical", "Debug", "Emergency", "Error", "Info", "Informational", "Notice", - "Trace", "Warn", "Warning" - ] - } - - private class ToplevelBeegoLoggers extends LoggerCall::Range, DataFlow::CallNode { - ToplevelBeegoLoggers() { - this.getTarget().hasQualifiedName([packagePath(), logsPackagePath()], getALogFunctionName()) - } - - override DataFlow::Node getAMessageComponent() { result = this.getASyntacticArgument() } - } - - private class BeegoLoggerMethods extends LoggerCall::Range, DataFlow::MethodCallNode { - BeegoLoggerMethods() { - this.getTarget().hasQualifiedName(logsPackagePath(), "BeeLogger", getALogFunctionName()) - } - - override DataFlow::Node getAMessageComponent() { result = this.getASyntacticArgument() } - } - - private class UtilLoggers extends LoggerCall::Range, DataFlow::CallNode { - UtilLoggers() { this.getTarget().hasQualifiedName(utilsPackagePath(), "Display") } - - override DataFlow::Node getAMessageComponent() { result = this.getASyntacticArgument() } - } - private class HtmlQuoteSanitizer extends SharedXss::Sanitizer { HtmlQuoteSanitizer() { exists(DataFlow::CallNode c | c.getTarget().hasQualifiedName(packagePath(), "Htmlquote") | diff --git a/go/ql/lib/semmle/go/frameworks/BeegoOrm.qll b/go/ql/lib/semmle/go/frameworks/BeegoOrm.qll index c1de0cf42442..925b0f19fa3f 100644 --- a/go/ql/lib/semmle/go/frameworks/BeegoOrm.qll +++ b/go/ql/lib/semmle/go/frameworks/BeegoOrm.qll @@ -14,57 +14,6 @@ module BeegoOrm { /** Gets the package name `github.com/astaxie/beego/orm`. */ string packagePath() { result = package("github.com/astaxie/beego", "orm") } - private class DbSink extends SQL::QueryString::Range { - DbSink() { - exists(Method m, string methodName, int argNum | - m.hasQualifiedName(packagePath(), "DB", methodName) and - ( - methodName = ["Exec", "Prepare", "Query", "QueryRow"] and - argNum = 0 - or - methodName = ["ExecContext", "PrepareContext", "QueryContext", "QueryRowContext"] and - argNum = 1 - ) - | - this = m.getACall().getArgument(argNum) - ) - } - } - - private class QueryBuilderSink extends SQL::QueryString::Range { - // Note this class doesn't do any escaping, unlike the true ORM part of the package - QueryBuilderSink() { - exists(Method impl | impl.implements(packagePath(), "QueryBuilder", _) | - this = impl.getACall().getASyntacticArgument() - ) and - this.getType().getUnderlyingType() instanceof StringType - } - } - - private class OrmerRawSink extends SQL::QueryString::Range { - OrmerRawSink() { - exists(Method impl | impl.implements(packagePath(), "Ormer", "Raw") | - this = impl.getACall().getArgument(0) - ) - } - } - - private class QuerySeterFilterRawSink extends SQL::QueryString::Range { - QuerySeterFilterRawSink() { - exists(Method impl | impl.implements(packagePath(), "QuerySeter", "FilterRaw") | - this = impl.getACall().getArgument(1) - ) - } - } - - private class ConditionRawSink extends SQL::QueryString::Range { - ConditionRawSink() { - exists(Method impl | impl.implements(packagePath(), "Condition", "Raw") | - this = impl.getACall().getArgument(1) - ) - } - } - private class OrmerSource extends StoredXss::Source { OrmerSource() { exists(Method impl | diff --git a/go/ql/lib/semmle/go/frameworks/Couchbase.qll b/go/ql/lib/semmle/go/frameworks/Couchbase.qll index 5eaa4d20c3ad..b5bfbcb22a2d 100644 --- a/go/ql/lib/semmle/go/frameworks/Couchbase.qll +++ b/go/ql/lib/semmle/go/frameworks/Couchbase.qll @@ -5,57 +5,23 @@ import go /** + * DEPRECATED + * * Provides models of commonly used functions in the official Couchbase Go SDK library. */ -module Couchbase { +deprecated module Couchbase { /** + * DEPRECATED + * * Gets a package path for the official Couchbase Go SDK library. * * Note that v1 and v2 have different APIs, but the names are disjoint so there is no need to * distinguish between them. */ - string packagePath() { + deprecated string packagePath() { result = package([ "gopkg.in/couchbase/gocb", "github.com/couchbase/gocb", "github.com/couchbaselabs/gocb" ], "") } - - /** - * A query used in an API function acting on a `Bucket` or `Cluster` struct of v1 of - * the official Couchbase Go library, gocb. - */ - private class CouchbaseV1Query extends NoSql::Query::Range { - CouchbaseV1Query() { - // func (b *Bucket) ExecuteAnalyticsQuery(q *AnalyticsQuery, params interface{}) (AnalyticsResults, error) - // func (b *Bucket) ExecuteN1qlQuery(q *N1qlQuery, params interface{}) (QueryResults, error) - // func (c *Cluster) ExecuteAnalyticsQuery(q *AnalyticsQuery, params interface{}) (AnalyticsResults, error) - // func (c *Cluster) ExecuteN1qlQuery(q *N1qlQuery, params interface{}) (QueryResults, error) - exists(Method meth, string structName, string methodName | - structName in ["Bucket", "Cluster"] and - methodName in ["ExecuteN1qlQuery", "ExecuteAnalyticsQuery"] and - meth.hasQualifiedName(packagePath(), structName, methodName) and - this = meth.getACall().getArgument(0) - ) - } - } - - /** - * A query used in an API function acting on a `Bucket` or `Cluster` struct of v1 of - * the official Couchbase Go library, gocb. - */ - private class CouchbaseV2Query extends NoSql::Query::Range { - CouchbaseV2Query() { - // func (c *Cluster) AnalyticsQuery(statement string, opts *AnalyticsOptions) (*AnalyticsResult, error) - // func (c *Cluster) Query(statement string, opts *QueryOptions) (*QueryResult, error) - // func (s *Scope) AnalyticsQuery(statement string, opts *AnalyticsOptions) (*AnalyticsResult, error) - // func (s *Scope) Query(statement string, opts *QueryOptions) (*QueryResult, error) - exists(Method meth, string structName, string methodName | - structName in ["Cluster", "Scope"] and - methodName in ["AnalyticsQuery", "Query"] and - meth.hasQualifiedName(packagePath(), structName, methodName) and - this = meth.getACall().getArgument(0) - ) - } - } } diff --git a/go/ql/lib/semmle/go/frameworks/ElazarlGoproxy.qll b/go/ql/lib/semmle/go/frameworks/ElazarlGoproxy.qll index 4d10c8af312d..b1bf4571216a 100644 --- a/go/ql/lib/semmle/go/frameworks/ElazarlGoproxy.qll +++ b/go/ql/lib/semmle/go/frameworks/ElazarlGoproxy.qll @@ -100,10 +100,4 @@ module ElazarlGoproxy { override int getFormatStringIndex() { result = 0 } } - - private class ProxyLog extends LoggerCall::Range, DataFlow::MethodCallNode { - ProxyLog() { this.getTarget() instanceof ProxyLogFunction } - - override DataFlow::Node getAMessageComponent() { result = this.getASyntacticArgument() } - } } diff --git a/go/ql/lib/semmle/go/frameworks/Glog.qll b/go/ql/lib/semmle/go/frameworks/Glog.qll index f9f5c9e3f11f..146b8a4f814b 100644 --- a/go/ql/lib/semmle/go/frameworks/Glog.qll +++ b/go/ql/lib/semmle/go/frameworks/Glog.qll @@ -40,14 +40,4 @@ module Glog { override int getFormatStringIndex() { result = super.getFirstPrintedArg() } } - - private class GlogCall extends LoggerCall::Range, DataFlow::CallNode { - GlogFunction callee; - - GlogCall() { this = callee.getACall() } - - override DataFlow::Node getAMessageComponent() { - result = this.getSyntacticArgument(any(int i | i >= callee.getFirstPrintedArg())) - } - } } diff --git a/go/ql/lib/semmle/go/frameworks/Logrus.qll b/go/ql/lib/semmle/go/frameworks/Logrus.qll index f7de9a75dae8..83278a4cd9e2 100644 --- a/go/ql/lib/semmle/go/frameworks/Logrus.qll +++ b/go/ql/lib/semmle/go/frameworks/Logrus.qll @@ -28,12 +28,6 @@ module Logrus { } } - private class LogCall extends LoggerCall::Range, DataFlow::CallNode { - LogCall() { this = any(LogFunction f).getACall() } - - override DataFlow::Node getAMessageComponent() { result = this.getASyntacticArgument() } - } - private class StringFormatters extends StringOps::Formatting::Range instanceof LogFunction { int argOffset; diff --git a/go/ql/lib/semmle/go/frameworks/NoSQL.qll b/go/ql/lib/semmle/go/frameworks/NoSQL.qll index c2469fc02ac1..36932149628e 100644 --- a/go/ql/lib/semmle/go/frameworks/NoSQL.qll +++ b/go/ql/lib/semmle/go/frameworks/NoSQL.qll @@ -31,84 +31,6 @@ module NoSql { ) } } - - /** - * Holds if method `name` of struct `Collection` from package - * [go.mongodb.org/mongo-driver/mongo](https://pkg.go.dev/go.mongodb.org/mongo-driver/mongo) - * interprets parameter `n` as a query. - */ - private predicate mongoDbCollectionMethod(string name, int n) { - // func (coll *Collection) CountDocuments(ctx context.Context, filter interface{}, - // opts ...*options.CountOptions) (int64, error) - name = "CountDocuments" and n = 1 - or - // func (coll *Collection) DeleteMany(ctx context.Context, filter interface{}, - // opts ...*options.DeleteOptions) (*DeleteResult, error) - name = "DeleteMany" and n = 1 - or - // func (coll *Collection) DeleteOne(ctx context.Context, filter interface{}, - // opts ...*options.DeleteOptions) (*DeleteResult, error) - name = "DeleteOne" and n = 1 - or - // func (coll *Collection) Distinct(ctx context.Context, fieldName string, filter interface{}, - // ...) ([]interface{}, error) - name = "Distinct" and n = 2 - or - // func (coll *Collection) Find(ctx context.Context, filter interface{}, - // opts ...*options.FindOptions) (*Cursor, error) - name = "Find" and n = 1 - or - // func (coll *Collection) FindOne(ctx context.Context, filter interface{}, - // opts ...*options.FindOneOptions) *SingleResult - name = "FindOne" and n = 1 - or - // func (coll *Collection) FindOneAndDelete(ctx context.Context, filter interface{}, ...) - // *SingleResult - name = "FindOneAndDelete" and n = 1 - or - // func (coll *Collection) FindOneAndReplace(ctx context.Context, filter interface{}, - // replacement interface{}, ...) *SingleResult - name = "FindOneAndReplace" and n = 1 - or - // func (coll *Collection) FindOneAndUpdate(ctx context.Context, filter interface{}, - // update interface{}, ...) *SingleResult - name = "FindOneAndUpdate" and n = 1 - or - // func (coll *Collection) ReplaceOne(ctx context.Context, filter interface{}, - // replacement interface{}, ...) (*UpdateResult, error) - name = "ReplaceOne" and n = 1 - or - // func (coll *Collection) UpdateMany(ctx context.Context, filter interface{}, - // update interface{}, ...) (*UpdateResult, error) - name = "UpdateMany" and n = 1 - or - // func (coll *Collection) UpdateOne(ctx context.Context, filter interface{}, - // update interface{}, ...) (*UpdateResult, error) - name = "UpdateOne" and n = 1 - or - // func (coll *Collection) Watch(ctx context.Context, pipeline interface{}, ...) - // (*ChangeStream, error) - name = "Watch" and n = 1 - or - // func (coll *Collection) Aggregate(ctx context.Context, pipeline interface{}, - // opts ...*options.AggregateOptions) (*Cursor, error) - name = "Aggregate" and n = 1 - } - - /** - * A query used in an API function acting on a `Collection` struct of package - * [go.mongodb.org/mongo-driver/mongo](https://pkg.go.dev/go.mongodb.org/mongo-driver/mongo). - */ - private class MongoDbCollectionQuery extends Range { - MongoDbCollectionQuery() { - exists(Method meth, string methodName, int n | - mongoDbCollectionMethod(methodName, n) and - meth.hasQualifiedName(package("go.mongodb.org/mongo-driver", "mongo"), "Collection", - methodName) and - this = meth.getACall().getArgument(n) - ) - } - } } /** diff --git a/go/ql/lib/semmle/go/frameworks/SQL.qll b/go/ql/lib/semmle/go/frameworks/SQL.qll index 1a6e22807812..a0e80fde1c9f 100644 --- a/go/ql/lib/semmle/go/frameworks/SQL.qll +++ b/go/ql/lib/semmle/go/frameworks/SQL.qll @@ -67,41 +67,34 @@ module SQL { */ abstract class Range extends DataFlow::Node { } + private class DefaultQueryString extends Range { + DefaultQueryString() { + exists(DataFlow::ArgumentNode arg | sinkNode(arg, "sql-injection") | + not arg instanceof DataFlow::ImplicitVarargsSlice and + this = arg + or + arg instanceof DataFlow::ImplicitVarargsSlice and + this = arg.getCall().getAnImplicitVarargsArgument() + ) + } + } + /** * An argument to an API of the squirrel library that is directly interpreted as SQL without * taking syntactic structure into account. */ private class SquirrelQueryString extends Range { SquirrelQueryString() { - exists(Function fn | - exists(string sq | - sq = - package([ - "github.com/Masterminds/squirrel", "gopkg.in/Masterminds/squirrel", - "github.com/lann/squirrel" - ], "") - | - fn.hasQualifiedName(sq, ["Delete", "Expr", "Insert", "Select", "Update"]) - or - exists(Method m, string builder | m = fn | - builder = ["DeleteBuilder", "InsertBuilder", "SelectBuilder", "UpdateBuilder"] and - m.hasQualifiedName(sq, builder, - ["Columns", "From", "Options", "OrderBy", "Prefix", "Suffix", "Where"]) - or - builder = "InsertBuilder" and - m.hasQualifiedName(sq, builder, ["Replace", "Into"]) - or - builder = "SelectBuilder" and - m.hasQualifiedName(sq, builder, - ["CrossJoin", "GroupBy", "InnerJoin", "LeftJoin", "RightJoin"]) - or - builder = "UpdateBuilder" and - m.hasQualifiedName(sq, builder, ["Set", "Table"]) - ) - ) and - this = fn.getACall().getArgument(0) + exists(string sq, Method m, string builder | + FlowExtensions::packageGrouping("squirrel", sq) and + builder = ["DeleteBuilder", "SelectBuilder", "UpdateBuilder"] | - this.getType().getUnderlyingType() instanceof StringType or + m.hasQualifiedName(sq, builder, "Where") and + this = m.getACall().getArgument(0) + ) and + ( + this.getType().getUnderlyingType() instanceof StringType + or this.getType().getUnderlyingType().(SliceType).getElementType() instanceof StringType ) } @@ -113,14 +106,6 @@ module SQL { /** A string that might identify package `go-pg/pg/orm` or a specific version of it. */ private string gopgorm() { result = package("github.com/go-pg/pg", "orm") } - /** A string that might identify package `github.com/rqlite/gorqlite` or `github.com/raindog308/gorqlite` or a specific version of it. */ - private string gorqlite() { - result = package(["github.com/rqlite/gorqlite", "github.com/raindog308/gorqlite"], "") - } - - /** A string that might identify package `github.com/gogf/gf/database/gdb` or a specific version of it. */ - private string gogf() { result = package("github.com/gogf/gf", "database/gdb") } - /** * A string argument to an API of `go-pg/pg` that is directly interpreted as SQL without * taking syntactic structure into account. @@ -185,94 +170,6 @@ module SQL { ) } } - - /** - * A string argument to an API of `github.com/rqlite/gorqlite`, or a specific version of it, that is directly interpreted as SQL without - * taking syntactic structure into account. - */ - private class GorqliteQueryString extends Range { - GorqliteQueryString() { - // func (conn *Connection) Query(sqlStatements []string) (results []QueryResult, err error) - // func (conn *Connection) QueryOne(sqlStatement string) (qr QueryResult, err error) - // func (conn *Connection) Queue(sqlStatements []string) (seq int64, err error) - // func (conn *Connection) QueueOne(sqlStatement string) (seq int64, err error) - // func (conn *Connection) Write(sqlStatements []string) (results []WriteResult, err error) - // func (conn *Connection) WriteOne(sqlStatement string) (wr WriteResult, err error) - exists(Method m, string name | m.hasQualifiedName(gorqlite(), "Connection", name) | - name = ["Query", "QueryOne", "Queue", "QueueOne", "Write", "WriteOne"] and - this = m.getACall().getArgument(0) - ) - } - } - - /** - * A string argument to an API of `github.com/gogf/gf/database/gdb`, or a specific version of it, that is directly interpreted as SQL without - * taking syntactic structure into account. - */ - private class GogfQueryString extends Range { - GogfQueryString() { - exists(Method m, string name | m.implements(gogf(), ["DB", "Core", "TX"], name) | - // func (c *Core) Exec(sql string, args ...interface{}) (result sql.Result, err error) - // func (c *Core) GetAll(sql string, args ...interface{}) (Result, error) - // func (c *Core) GetArray(sql string, args ...interface{}) ([]Value, error) - // func (c *Core) GetCount(sql string, args ...interface{}) (int, error) - // func (c *Core) GetOne(sql string, args ...interface{}) (Record, error) - // func (c *Core) GetValue(sql string, args ...interface{}) (Value, error) - // func (c *Core) Prepare(sql string, execOnMaster ...bool) (*Stmt, error) - // func (c *Core) Query(sql string, args ...interface{}) (rows *sql.Rows, err error) - // func (c *Core) Raw(rawSql string, args ...interface{}) *Model - name = - [ - "Query", "Exec", "Prepare", "GetAll", "GetOne", "GetValue", "GetArray", "GetCount", - "Raw" - ] and - this = m.getACall().getArgument(0) - or - // func (c *Core) GetScan(pointer interface{}, sql string, args ...interface{}) error - // func (c *Core) GetStruct(pointer interface{}, sql string, args ...interface{}) error - // func (c *Core) GetStructs(pointer interface{}, sql string, args ...interface{}) error - name = ["GetScan", "GetStruct", "GetStructs"] and - this = m.getACall().getArgument(1) - or - // func (c *Core) DoCommit(ctx context.Context, link Link, sql string, args []interface{}) (newSql string, newArgs []interface{}, err error) - // func (c *Core) DoExec(ctx context.Context, link Link, sql string, args ...interface{}) (result sql.Result, err error) - // func (c *Core) DoGetAll(ctx context.Context, link Link, sql string, args ...interface{}) (result Result, err error) - // func (c *Core) DoPrepare(ctx context.Context, link Link, sql string) (*Stmt, error) - // func (c *Core) DoQuery(ctx context.Context, link Link, sql string, args ...interface{}) (rows *sql.Rows, err error) - name = ["DoGetAll", "DoQuery", "DoExec", "DoCommit", "DoPrepare"] and - this = m.getACall().getArgument(2) - ) - } - } - } - - /** A model for sinks of GORM. */ - private class GormSink extends SQL::QueryString::Range { - GormSink() { - exists(Method meth, string package, string name | - meth.hasQualifiedName(package, "DB", name) and - this = meth.getACall().getSyntacticArgument(0) and - package = Gorm::packagePath() and - name in [ - "Where", "Raw", "Order", "Not", "Or", "Select", "Table", "Group", "Having", "Joins", - "Exec", "Distinct", "Pluck" - ] - ) - } - } - - /** A model for sinks of github.com/jmoiron/sqlx. */ - private class SqlxSink extends SQL::QueryString::Range { - SqlxSink() { - exists(Method meth, string name, int n | - meth.hasQualifiedName(package("github.com/jmoiron/sqlx", ""), ["DB", "Tx"], name) and - this = meth.getACall().getArgument(n) - | - name = ["Select", "Get"] and n = 1 - or - name = ["MustExec", "Queryx", "NamedExec", "NamedQuery"] and n = 0 - ) - } } } @@ -291,71 +188,25 @@ module Gorm { */ module Xorm { /** Gets the package name for Xorm. */ - string packagePath() { result = package(["xorm.io/xorm", "github.com/go-xorm/xorm"], "") } + string packagePath() { FlowExtensions::packageGrouping("xorm", result) } /** A model for sinks of XORM. */ private class XormSink extends SQL::QueryString::Range { XormSink() { - exists(Method meth, string type, string name, int n | + exists(Method meth, string type, string name | meth.hasQualifiedName(Xorm::packagePath(), type, name) and - this = meth.getACall().getSyntacticArgument(n) and - type = ["Engine", "Session"] + type = ["Engine", "Session"] and + name = ["Exec", "Query", "QueryInterface", "QueryString"] | - name = - [ - "Query", "Exec", "QueryString", "QueryInterface", "SQL", "Where", "And", "Or", "Alias", - "NotIn", "In", "Select", "SetExpr", "OrderBy", "Having", "GroupBy" - ] and - n = 0 - or - name = ["SumInt", "Sum", "Sums", "SumsInt"] and n = 1 - or - name = "Join" and n = [0, 1, 2] + this = meth.getACall().getSyntacticArgument(0) ) } } } /** + * DEPRECATED + * * Provides classes for working with the [Bun](https://bun.uptrace.dev/) package. */ -module Bun { - /** Gets the package name for Bun package. */ - private string packagePath() { result = package("github.com/uptrace/bun", "") } - - /** A model for sinks of Bun. */ - private class BunSink extends SQL::QueryString::Range { - BunSink() { - exists(Function f, string m, int arg | this = f.getACall().getArgument(arg) | - f.hasQualifiedName(packagePath(), m) and - m = "NewRawQuery" and - arg = 1 - ) - or - exists(Method f, string tp, string m, int arg | this = f.getACall().getArgument(arg) | - f.hasQualifiedName(packagePath(), tp, m) and - ( - tp = ["DB", "Conn"] and - m = ["ExecContext", "PrepareContext", "QueryContext", "QueryRowContext"] and - arg = 1 - or - tp = ["DB", "Conn"] and - m = ["Exec", "NewRaw", "Prepare", "Query", "QueryRow", "Raw"] and - arg = 0 - or - tp.matches("%Query") and - m = - [ - "ColumnExpr", "DistinctOn", "For", "GroupExpr", "Having", "ModelTableExpr", - "OrderExpr", "TableExpr", "Where", "WhereOr" - ] and - arg = 0 - or - tp = "RawQuery" and - m = "NewRaw" and - arg = 0 - ) - ) - } - } -} +deprecated module Bun { } diff --git a/go/ql/lib/semmle/go/frameworks/Spew.qll b/go/ql/lib/semmle/go/frameworks/Spew.qll index b12bd0fed815..f49a4aa4d89d 100644 --- a/go/ql/lib/semmle/go/frameworks/Spew.qll +++ b/go/ql/lib/semmle/go/frameworks/Spew.qll @@ -33,16 +33,6 @@ module Spew { override int getFormatStringIndex() { result = super.getFirstPrintedArg() } } - private class SpewCall extends LoggerCall::Range, DataFlow::CallNode { - SpewFunction target; - - SpewCall() { this = target.getACall() } - - override DataFlow::Node getAMessageComponent() { - result = this.getSyntacticArgument(any(int i | i >= target.getFirstPrintedArg())) - } - } - // These are expressed using TaintTracking::FunctionModel because varargs functions don't work with Models-as-Data sumamries yet. /** The `Sprint` function or one of its variants. */ class Sprinter extends TaintTracking::FunctionModel { diff --git a/go/ql/lib/semmle/go/frameworks/Zap.qll b/go/ql/lib/semmle/go/frameworks/Zap.qll index 359f9aba4107..0928d2b0595c 100644 --- a/go/ql/lib/semmle/go/frameworks/Zap.qll +++ b/go/ql/lib/semmle/go/frameworks/Zap.qll @@ -34,18 +34,6 @@ module Zap { override int getFormatStringIndex() { result = 0 } } - /** - * A call to a logger function in Zap. - * - * Functions which add data to be included the next time a direct logging - * function is called are included. - */ - private class ZapCall extends LoggerCall::Range, DataFlow::MethodCallNode { - ZapCall() { this = any(ZapFunction f).getACall() } - - override DataFlow::Node getAMessageComponent() { result = this.getASyntacticArgument() } - } - // These are expressed using TaintTracking::FunctionModel because varargs functions don't work with Models-as-Data sumamries yet. /** The function `Fields` that creates an `Option` that can be added to the logger out of `Field`s. */ class FieldsFunction extends TaintTracking::FunctionModel { diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/DatabaseSql.qll b/go/ql/lib/semmle/go/frameworks/stdlib/DatabaseSql.qll index 845225af5bd2..f41326887961 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/DatabaseSql.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/DatabaseSql.qll @@ -26,7 +26,7 @@ module DatabaseSql { override DataFlow::Node getAResult() { result = this.getResult(0) } override SQL::QueryString getAQueryString() { - result = this.getAnArgument() + result = this.getASyntacticArgument() or // attempt to resolve a `QueryString` for `Stmt`s using local data flow. t = "Stmt" and @@ -34,24 +34,6 @@ module DatabaseSql { } } - /** A query string used in an API function of the `database/sql` package. */ - private class QueryString extends SQL::QueryString::Range { - QueryString() { - exists(Method meth, string base, string t, string m, int n | - t = ["DB", "Tx", "Conn"] and - meth.hasQualifiedName("database/sql", t, m) and - this = meth.getACall().getArgument(n) - | - base = ["Exec", "Prepare", "Query", "QueryRow"] and - ( - m = base and n = 0 - or - m = base + "Context" and n = 1 - ) - ) - } - } - /** A query in the standard `database/sql/driver` package. */ private class DriverQuery extends SQL::Query::Range, DataFlow::MethodCallNode { DriverQuery() { @@ -78,36 +60,13 @@ module DatabaseSql { override DataFlow::Node getAResult() { result = this.getResult(0) } override SQL::QueryString getAQueryString() { - result = this.getAnArgument() + result = this.getASyntacticArgument() or this.getTarget().hasQualifiedName("database/sql/driver", "Stmt") and result = this.getReceiver().getAPredecessor*().(DataFlow::MethodCallNode).getAnArgument() } } - /** A query string used in an API function of the standard `database/sql/driver` package. */ - private class DriverQueryString extends SQL::QueryString::Range { - DriverQueryString() { - exists(Method meth, int n | - ( - meth.hasQualifiedName("database/sql/driver", "Execer", "Exec") and n = 0 - or - meth.hasQualifiedName("database/sql/driver", "ExecerContext", "ExecContext") and n = 1 - or - meth.hasQualifiedName("database/sql/driver", "Conn", "Prepare") and n = 0 - or - meth.hasQualifiedName("database/sql/driver", "ConnPrepareContext", "PrepareContext") and - n = 1 - or - meth.hasQualifiedName("database/sql/driver", "Queryer", "Query") and n = 0 - or - meth.hasQualifiedName("database/sql/driver", "QueryerContext", "QueryContext") and n = 1 - ) and - this = meth.getACall().getArgument(n) - ) - } - } - // These are expressed using TaintTracking::FunctionModel because varargs functions don't work with Models-as-Data sumamries yet. private class SqlMethodModels extends TaintTracking::FunctionModel, Method { FunctionInput inp; diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/Fmt.qll b/go/ql/lib/semmle/go/frameworks/stdlib/Fmt.qll index 54794ea21c9e..6adbd542e9b6 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/Fmt.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/Fmt.qll @@ -41,13 +41,6 @@ module Fmt { Printer() { this.hasQualifiedName("fmt", ["Print", "Printf", "Println"]) } } - /** A call to `Print` or similar. */ - private class PrintCall extends LoggerCall::Range, DataFlow::CallNode { - PrintCall() { this.getTarget() instanceof Printer } - - override DataFlow::Node getAMessageComponent() { result = this.getASyntacticArgument() } - } - /** The `Fprint` function or one of its variants. */ private class Fprinter extends TaintTracking::FunctionModel { Fprinter() { diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/Log.qll b/go/ql/lib/semmle/go/frameworks/stdlib/Log.qll index 5b402fca1b7e..ca74160bf0df 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/Log.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/Log.qll @@ -32,16 +32,6 @@ module Log { override int getFormatStringIndex() { result = 0 } } - private class LogCall extends LoggerCall::Range, DataFlow::CallNode { - LogFunction target; - - LogCall() { this = target.getACall() } - - override DataFlow::Node getAMessageComponent() { - result = this.getSyntacticArgument(any(int i | i >= target.getFirstPrintedArg())) - } - } - /** A fatal log function, which calls `os.Exit`. */ private class FatalLogFunction extends Function { FatalLogFunction() { this.hasQualifiedName("log", ["Fatal", "Fatalf", "Fatalln"]) } diff --git a/go/ql/test/library-tests/semmle/go/frameworks/BeegoOrm/SqlInjection.expected b/go/ql/test/library-tests/semmle/go/frameworks/BeegoOrm/SqlInjection.expected index 6cc1e09486b7..1198f8d41a9b 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/BeegoOrm/SqlInjection.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/BeegoOrm/SqlInjection.expected @@ -32,40 +32,61 @@ | test.go:59:31:59:39 | untrusted | test.go:57:15:57:41 | call to UserAgent | test.go:59:31:59:39 | untrusted | This query depends on a $@. | test.go:57:15:57:41 | call to UserAgent | user-provided value | | test.go:65:19:65:27 | untrusted | test.go:63:15:63:41 | call to UserAgent | test.go:65:19:65:27 | untrusted | This query depends on a $@. | test.go:63:15:63:41 | call to UserAgent | user-provided value | edges -| test.go:11:15:11:41 | call to UserAgent | test.go:13:11:13:19 | untrusted | provenance | Src:MaD:1 | -| test.go:11:15:11:41 | call to UserAgent | test.go:14:23:14:31 | untrusted | provenance | Src:MaD:1 | -| test.go:11:15:11:41 | call to UserAgent | test.go:15:14:15:22 | untrusted | provenance | Src:MaD:1 | -| test.go:11:15:11:41 | call to UserAgent | test.go:16:26:16:34 | untrusted | provenance | Src:MaD:1 | -| test.go:11:15:11:41 | call to UserAgent | test.go:17:12:17:20 | untrusted | provenance | Src:MaD:1 | -| test.go:11:15:11:41 | call to UserAgent | test.go:18:24:18:32 | untrusted | provenance | Src:MaD:1 | -| test.go:11:15:11:41 | call to UserAgent | test.go:19:15:19:23 | untrusted | provenance | Src:MaD:1 | -| test.go:11:15:11:41 | call to UserAgent | test.go:20:27:20:35 | untrusted | provenance | Src:MaD:1 | -| test.go:25:15:25:41 | call to UserAgent | test.go:28:12:28:20 | untrusted | provenance | Src:MaD:1 | -| test.go:25:15:25:41 | call to UserAgent | test.go:29:10:29:18 | untrusted | provenance | Src:MaD:1 | -| test.go:25:15:25:41 | call to UserAgent | test.go:30:15:30:23 | untrusted | provenance | Src:MaD:1 | -| test.go:25:15:25:41 | call to UserAgent | test.go:31:14:31:22 | untrusted | provenance | Src:MaD:1 | -| test.go:25:15:25:41 | call to UserAgent | test.go:32:15:32:23 | untrusted | provenance | Src:MaD:1 | -| test.go:25:15:25:41 | call to UserAgent | test.go:33:8:33:16 | untrusted | provenance | Src:MaD:1 | -| test.go:25:15:25:41 | call to UserAgent | test.go:34:11:34:19 | untrusted | provenance | Src:MaD:1 | -| test.go:25:15:25:41 | call to UserAgent | test.go:35:9:35:17 | untrusted | provenance | Src:MaD:1 | -| test.go:25:15:25:41 | call to UserAgent | test.go:36:8:36:16 | untrusted | provenance | Src:MaD:1 | -| test.go:25:15:25:41 | call to UserAgent | test.go:37:8:37:16 | untrusted | provenance | Src:MaD:1 | -| test.go:25:15:25:41 | call to UserAgent | test.go:38:13:38:21 | untrusted | provenance | Src:MaD:1 | -| test.go:25:15:25:41 | call to UserAgent | test.go:39:13:39:21 | untrusted | provenance | Src:MaD:1 | -| test.go:25:15:25:41 | call to UserAgent | test.go:40:12:40:20 | untrusted | provenance | Src:MaD:1 | -| test.go:25:15:25:41 | call to UserAgent | test.go:41:12:41:20 | untrusted | provenance | Src:MaD:1 | -| test.go:25:15:25:41 | call to UserAgent | test.go:42:9:42:17 | untrusted | provenance | Src:MaD:1 | -| test.go:25:15:25:41 | call to UserAgent | test.go:43:12:43:20 | untrusted | provenance | Src:MaD:1 | -| test.go:25:15:25:41 | call to UserAgent | test.go:44:16:44:24 | untrusted | provenance | Src:MaD:1 | -| test.go:25:15:25:41 | call to UserAgent | test.go:45:12:45:20 | untrusted | provenance | Src:MaD:1 | -| test.go:25:15:25:41 | call to UserAgent | test.go:46:14:46:22 | untrusted | provenance | Src:MaD:1 | -| test.go:26:16:26:42 | call to UserAgent | test.go:44:27:44:36 | untrusted2 | provenance | Src:MaD:1 | -| test.go:26:16:26:42 | call to UserAgent | test.go:46:25:46:34 | untrusted2 | provenance | Src:MaD:1 | -| test.go:50:15:50:41 | call to UserAgent | test.go:52:12:52:20 | untrusted | provenance | Src:MaD:1 | -| test.go:57:15:57:41 | call to UserAgent | test.go:59:31:59:39 | untrusted | provenance | Src:MaD:1 | -| test.go:63:15:63:41 | call to UserAgent | test.go:65:19:65:27 | untrusted | provenance | Src:MaD:1 | +| test.go:11:15:11:41 | call to UserAgent | test.go:13:11:13:19 | untrusted | provenance | Src:MaD:22 Sink:MaD:2 | +| test.go:11:15:11:41 | call to UserAgent | test.go:14:23:14:31 | untrusted | provenance | Src:MaD:22 Sink:MaD:3 | +| test.go:11:15:11:41 | call to UserAgent | test.go:15:14:15:22 | untrusted | provenance | Src:MaD:22 Sink:MaD:4 | +| test.go:11:15:11:41 | call to UserAgent | test.go:16:26:16:34 | untrusted | provenance | Src:MaD:22 Sink:MaD:5 | +| test.go:11:15:11:41 | call to UserAgent | test.go:17:12:17:20 | untrusted | provenance | Src:MaD:22 Sink:MaD:6 | +| test.go:11:15:11:41 | call to UserAgent | test.go:18:24:18:32 | untrusted | provenance | Src:MaD:22 Sink:MaD:7 | +| test.go:11:15:11:41 | call to UserAgent | test.go:19:15:19:23 | untrusted | provenance | Src:MaD:22 Sink:MaD:8 | +| test.go:11:15:11:41 | call to UserAgent | test.go:20:27:20:35 | untrusted | provenance | Src:MaD:22 Sink:MaD:9 | +| test.go:25:15:25:41 | call to UserAgent | test.go:28:12:28:20 | untrusted | provenance | Src:MaD:22 | +| test.go:25:15:25:41 | call to UserAgent | test.go:29:10:29:18 | untrusted | provenance | Src:MaD:22 | +| test.go:25:15:25:41 | call to UserAgent | test.go:30:15:30:23 | untrusted | provenance | Src:MaD:22 Sink:MaD:13 | +| test.go:25:15:25:41 | call to UserAgent | test.go:31:14:31:22 | untrusted | provenance | Src:MaD:22 Sink:MaD:15 | +| test.go:25:15:25:41 | call to UserAgent | test.go:32:15:32:23 | untrusted | provenance | Src:MaD:22 Sink:MaD:18 | +| test.go:25:15:25:41 | call to UserAgent | test.go:33:8:33:16 | untrusted | provenance | Src:MaD:22 Sink:MaD:16 | +| test.go:25:15:25:41 | call to UserAgent | test.go:34:11:34:19 | untrusted | provenance | Src:MaD:22 Sink:MaD:20 | +| test.go:25:15:25:41 | call to UserAgent | test.go:35:9:35:17 | untrusted | provenance | Src:MaD:22 Sink:MaD:11 | +| test.go:25:15:25:41 | call to UserAgent | test.go:36:8:36:16 | untrusted | provenance | Src:MaD:22 Sink:MaD:17 | +| test.go:25:15:25:41 | call to UserAgent | test.go:37:8:37:16 | untrusted | provenance | Src:MaD:22 | +| test.go:25:15:25:41 | call to UserAgent | test.go:38:13:38:21 | untrusted | provenance | Src:MaD:22 | +| test.go:25:15:25:41 | call to UserAgent | test.go:39:13:39:21 | untrusted | provenance | Src:MaD:22 | +| test.go:25:15:25:41 | call to UserAgent | test.go:40:12:40:20 | untrusted | provenance | Src:MaD:22 Sink:MaD:12 | +| test.go:25:15:25:41 | call to UserAgent | test.go:41:12:41:20 | untrusted | provenance | Src:MaD:22 | +| test.go:25:15:25:41 | call to UserAgent | test.go:42:9:42:17 | untrusted | provenance | Src:MaD:22 | +| test.go:25:15:25:41 | call to UserAgent | test.go:43:12:43:20 | untrusted | provenance | Src:MaD:22 | +| test.go:25:15:25:41 | call to UserAgent | test.go:44:16:44:24 | untrusted | provenance | Src:MaD:22 Sink:MaD:14 | +| test.go:25:15:25:41 | call to UserAgent | test.go:45:12:45:20 | untrusted | provenance | Src:MaD:22 | +| test.go:25:15:25:41 | call to UserAgent | test.go:46:14:46:22 | untrusted | provenance | Src:MaD:22 Sink:MaD:19 | +| test.go:26:16:26:42 | call to UserAgent | test.go:44:27:44:36 | untrusted2 | provenance | Src:MaD:22 | +| test.go:26:16:26:42 | call to UserAgent | test.go:46:25:46:34 | untrusted2 | provenance | Src:MaD:22 Sink:MaD:19 | +| test.go:50:15:50:41 | call to UserAgent | test.go:52:12:52:20 | untrusted | provenance | Src:MaD:22 Sink:MaD:10 | +| test.go:57:15:57:41 | call to UserAgent | test.go:59:31:59:39 | untrusted | provenance | Src:MaD:22 Sink:MaD:21 | +| test.go:63:15:63:41 | call to UserAgent | test.go:65:19:65:27 | untrusted | provenance | Src:MaD:22 Sink:MaD:1 | models -| 1 | Source: net/http; Request; true; UserAgent; ; ; ReturnValue; remote; manual | +| 1 | Sink: group:beego-orm; Condition; true; Raw; ; ; Argument[1]; sql-injection; manual | +| 2 | Sink: group:beego-orm; DB; true; Exec; ; ; Argument[0]; sql-injection; manual | +| 3 | Sink: group:beego-orm; DB; true; ExecContext; ; ; Argument[1]; sql-injection; manual | +| 4 | Sink: group:beego-orm; DB; true; Prepare; ; ; Argument[0]; sql-injection; manual | +| 5 | Sink: group:beego-orm; DB; true; PrepareContext; ; ; Argument[1]; sql-injection; manual | +| 6 | Sink: group:beego-orm; DB; true; Query; ; ; Argument[0]; sql-injection; manual | +| 7 | Sink: group:beego-orm; DB; true; QueryContext; ; ; Argument[1]; sql-injection; manual | +| 8 | Sink: group:beego-orm; DB; true; QueryRow; ; ; Argument[0]; sql-injection; manual | +| 9 | Sink: group:beego-orm; DB; true; QueryRowContext; ; ; Argument[1]; sql-injection; manual | +| 10 | Sink: group:beego-orm; Ormer; true; Raw; ; ; Argument[0]; sql-injection; manual | +| 11 | Sink: group:beego-orm; QueryBuilder; true; And; ; ; Argument[0]; sql-injection; manual | +| 12 | Sink: group:beego-orm; QueryBuilder; true; Having; ; ; Argument[0]; sql-injection; manual | +| 13 | Sink: group:beego-orm; QueryBuilder; true; InnerJoin; ; ; Argument[0]; sql-injection; manual | +| 14 | Sink: group:beego-orm; QueryBuilder; true; InsertInto; ; ; Argument[0..1]; sql-injection; manual | +| 15 | Sink: group:beego-orm; QueryBuilder; true; LeftJoin; ; ; Argument[0]; sql-injection; manual | +| 16 | Sink: group:beego-orm; QueryBuilder; true; On; ; ; Argument[0]; sql-injection; manual | +| 17 | Sink: group:beego-orm; QueryBuilder; true; Or; ; ; Argument[0]; sql-injection; manual | +| 18 | Sink: group:beego-orm; QueryBuilder; true; RightJoin; ; ; Argument[0]; sql-injection; manual | +| 19 | Sink: group:beego-orm; QueryBuilder; true; Subquery; ; ; Argument[0..1]; sql-injection; manual | +| 20 | Sink: group:beego-orm; QueryBuilder; true; Where; ; ; Argument[0]; sql-injection; manual | +| 21 | Sink: group:beego-orm; QuerySeter; true; FilterRaw; ; ; Argument[1]; sql-injection; manual | +| 22 | Source: net/http; Request; true; UserAgent; ; ; ReturnValue; remote; manual | nodes | test.go:11:15:11:41 | call to UserAgent | semmle.label | call to UserAgent | | test.go:13:11:13:19 | untrusted | semmle.label | untrusted | diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/Gorm/QueryString.expected b/go/ql/test/library-tests/semmle/go/frameworks/SQL/Gorm/QueryString.expected new file mode 100644 index 000000000000..db33d6d2504a --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/frameworks/SQL/Gorm/QueryString.expected @@ -0,0 +1,3 @@ +testFailures +invalidModelRow +failures diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/Gorm/QueryString.ql b/go/ql/test/library-tests/semmle/go/frameworks/SQL/Gorm/QueryString.ql new file mode 100644 index 000000000000..eeb43a82fadd --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/frameworks/SQL/Gorm/QueryString.ql @@ -0,0 +1,60 @@ +import go +import semmle.go.dataflow.ExternalFlow +import ModelValidation +import TestUtilities.InlineExpectationsTest + +module SqlTest implements TestSig { + string getARelevantTag() { result = "query" } + + predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "query" and + exists(SQL::Query q, SQL::QueryString qs | qs = q.getAQueryString() | + q.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), + location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and + element = q.toString() and + value = qs.toString() + ) + } +} + +module QueryString implements TestSig { + string getARelevantTag() { result = "querystring" } + + predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "querystring" and + element = "" and + exists(SQL::QueryString qs | not exists(SQL::Query q | qs = q.getAQueryString()) | + qs.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), + location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and + value = qs.toString() + ) + } +} + +module Config implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node n) { n.asExpr() instanceof StringLit } + + predicate isSink(DataFlow::Node n) { + n = any(DataFlow::CallNode cn | cn.getTarget().getName() = "sink").getAnArgument() + } +} + +module Flow = TaintTracking::Global; + +module TaintFlow implements TestSig { + string getARelevantTag() { result = "flowfrom" } + + predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "flowfrom" and + element = "" and + exists(DataFlow::Node fromNode, DataFlow::Node toNode | + toNode + .hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), + location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and + Flow::flow(fromNode, toNode) and + value = fromNode.asExpr().(StringLit).getValue() + ) + } +} + +import MakeTest> diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/Gorm/gorm.expected b/go/ql/test/library-tests/semmle/go/frameworks/SQL/Gorm/gorm.expected deleted file mode 100644 index ca70ed07c33d..000000000000 --- a/go/ql/test/library-tests/semmle/go/frameworks/SQL/Gorm/gorm.expected +++ /dev/null @@ -1,25 +0,0 @@ -| gorm.go:20:12:20:20 | untrusted | github.com/jinzhu/gorm | DB | Where | -| gorm.go:21:10:21:18 | untrusted | github.com/jinzhu/gorm | DB | Raw | -| gorm.go:22:10:22:18 | untrusted | github.com/jinzhu/gorm | DB | Not | -| gorm.go:23:12:23:20 | untrusted | github.com/jinzhu/gorm | DB | Order | -| gorm.go:24:9:24:17 | untrusted | github.com/jinzhu/gorm | DB | Or | -| gorm.go:25:13:25:21 | untrusted | github.com/jinzhu/gorm | DB | Select | -| gorm.go:26:12:26:20 | untrusted | github.com/jinzhu/gorm | DB | Table | -| gorm.go:27:12:27:20 | untrusted | github.com/jinzhu/gorm | DB | Group | -| gorm.go:28:13:28:21 | untrusted | github.com/jinzhu/gorm | DB | Having | -| gorm.go:29:12:29:20 | untrusted | github.com/jinzhu/gorm | DB | Joins | -| gorm.go:30:11:30:19 | untrusted | github.com/jinzhu/gorm | DB | Exec | -| gorm.go:31:12:31:20 | untrusted | github.com/jinzhu/gorm | DB | Pluck | -| gorm.go:34:12:34:20 | untrusted | gorm.io/gorm | DB | Where | -| gorm.go:35:10:35:18 | untrusted | gorm.io/gorm | DB | Raw | -| gorm.go:36:10:36:18 | untrusted | gorm.io/gorm | DB | Not | -| gorm.go:37:12:37:20 | untrusted | gorm.io/gorm | DB | Order | -| gorm.go:38:9:38:17 | untrusted | gorm.io/gorm | DB | Or | -| gorm.go:39:13:39:21 | untrusted | gorm.io/gorm | DB | Select | -| gorm.go:40:12:40:20 | untrusted | gorm.io/gorm | DB | Table | -| gorm.go:41:12:41:20 | untrusted | gorm.io/gorm | DB | Group | -| gorm.go:42:13:42:21 | untrusted | gorm.io/gorm | DB | Having | -| gorm.go:43:12:43:20 | untrusted | gorm.io/gorm | DB | Joins | -| gorm.go:44:11:44:19 | untrusted | gorm.io/gorm | DB | Exec | -| gorm.go:45:15:45:23 | untrusted | gorm.io/gorm | DB | Distinct | -| gorm.go:46:12:46:20 | untrusted | gorm.io/gorm | DB | Pluck | diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/Gorm/gorm.go b/go/ql/test/library-tests/semmle/go/frameworks/SQL/Gorm/gorm.go index bee8edbf7af8..2d736e2407c9 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/SQL/Gorm/gorm.go +++ b/go/ql/test/library-tests/semmle/go/frameworks/SQL/Gorm/gorm.go @@ -13,36 +13,35 @@ func getUntrustedString() string { } func main() { - untrusted := getUntrustedString() db1 := gorm1.DB{} - db1.Where(untrusted) - db1.Raw(untrusted) - db1.Not(untrusted) - db1.Order(untrusted) - db1.Or(untrusted) - db1.Select(untrusted) - db1.Table(untrusted) - db1.Group(untrusted) - db1.Having(untrusted) - db1.Joins(untrusted) - db1.Exec(untrusted) - db1.Pluck(untrusted, nil) + db1.Where(untrusted) // $ querystring=untrusted + db1.Raw(untrusted) // $ querystring=untrusted + db1.Not(untrusted) // $ querystring=untrusted + db1.Order(untrusted) // $ querystring=untrusted + db1.Or(untrusted) // $ querystring=untrusted + db1.Select(untrusted) // $ querystring=untrusted + db1.Table(untrusted) // $ querystring=untrusted + db1.Group(untrusted) // $ querystring=untrusted + db1.Having(untrusted) // $ querystring=untrusted + db1.Joins(untrusted) // $ querystring=untrusted + db1.Exec(untrusted) // $ querystring=untrusted + db1.Pluck(untrusted, nil) // $ querystring=untrusted db2 := gorm2.DB{} - db2.Where(untrusted) - db2.Raw(untrusted) - db2.Not(untrusted) - db2.Order(untrusted) - db2.Or(untrusted) - db2.Select(untrusted) - db2.Table(untrusted) - db2.Group(untrusted) - db2.Having(untrusted) - db2.Joins(untrusted) - db2.Exec(untrusted) - db2.Distinct(untrusted) - db2.Pluck(untrusted, nil) + db2.Where(untrusted) // $ querystring=untrusted + db2.Raw(untrusted) // $ querystring=untrusted + db2.Not(untrusted) // $ querystring=untrusted + db2.Order(untrusted) // $ querystring=untrusted + db2.Or(untrusted) // $ querystring=untrusted + db2.Select(untrusted) // $ querystring=untrusted + db2.Table(untrusted) // $ querystring=untrusted + db2.Group(untrusted) // $ querystring=untrusted + db2.Having(untrusted) // $ querystring=untrusted + db2.Joins(untrusted) // $ querystring=untrusted + db2.Exec(untrusted) // $ querystring=untrusted + db2.Distinct(untrusted) // $ querystring=untrusted + db2.Pluck(untrusted, nil) // $ querystring=untrusted } diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/Gorm/gorm.ql b/go/ql/test/library-tests/semmle/go/frameworks/SQL/Gorm/gorm.ql deleted file mode 100644 index e08b506deaf1..000000000000 --- a/go/ql/test/library-tests/semmle/go/frameworks/SQL/Gorm/gorm.ql +++ /dev/null @@ -1,5 +0,0 @@ -import go - -from SQL::QueryString qs, Method meth, string a, string b, string c -where meth.hasQualifiedName(a, b, c) and qs = meth.getACall().getSyntacticArgument(0) -select qs, a, b, c diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/Sqlx/QueryString.expected b/go/ql/test/library-tests/semmle/go/frameworks/SQL/Sqlx/QueryString.expected new file mode 100644 index 000000000000..db33d6d2504a --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/frameworks/SQL/Sqlx/QueryString.expected @@ -0,0 +1,3 @@ +testFailures +invalidModelRow +failures diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/Sqlx/QueryString.ql b/go/ql/test/library-tests/semmle/go/frameworks/SQL/Sqlx/QueryString.ql new file mode 100644 index 000000000000..eeb43a82fadd --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/frameworks/SQL/Sqlx/QueryString.ql @@ -0,0 +1,60 @@ +import go +import semmle.go.dataflow.ExternalFlow +import ModelValidation +import TestUtilities.InlineExpectationsTest + +module SqlTest implements TestSig { + string getARelevantTag() { result = "query" } + + predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "query" and + exists(SQL::Query q, SQL::QueryString qs | qs = q.getAQueryString() | + q.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), + location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and + element = q.toString() and + value = qs.toString() + ) + } +} + +module QueryString implements TestSig { + string getARelevantTag() { result = "querystring" } + + predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "querystring" and + element = "" and + exists(SQL::QueryString qs | not exists(SQL::Query q | qs = q.getAQueryString()) | + qs.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), + location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and + value = qs.toString() + ) + } +} + +module Config implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node n) { n.asExpr() instanceof StringLit } + + predicate isSink(DataFlow::Node n) { + n = any(DataFlow::CallNode cn | cn.getTarget().getName() = "sink").getAnArgument() + } +} + +module Flow = TaintTracking::Global; + +module TaintFlow implements TestSig { + string getARelevantTag() { result = "flowfrom" } + + predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "flowfrom" and + element = "" and + exists(DataFlow::Node fromNode, DataFlow::Node toNode | + toNode + .hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), + location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and + Flow::flow(fromNode, toNode) and + value = fromNode.asExpr().(StringLit).getValue() + ) + } +} + +import MakeTest> diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/Sqlx/sqlx.expected b/go/ql/test/library-tests/semmle/go/frameworks/SQL/Sqlx/sqlx.expected deleted file mode 100644 index 0540a78fb343..000000000000 --- a/go/ql/test/library-tests/semmle/go/frameworks/SQL/Sqlx/sqlx.expected +++ /dev/null @@ -1,12 +0,0 @@ -| sqlx.go:15:17:15:25 | untrusted | -| sqlx.go:16:14:16:22 | untrusted | -| sqlx.go:17:14:17:22 | untrusted | -| sqlx.go:18:12:18:20 | untrusted | -| sqlx.go:19:15:19:23 | untrusted | -| sqlx.go:20:16:20:24 | untrusted | -| sqlx.go:23:17:23:25 | untrusted | -| sqlx.go:24:14:24:22 | untrusted | -| sqlx.go:25:14:25:22 | untrusted | -| sqlx.go:26:12:26:20 | untrusted | -| sqlx.go:27:15:27:23 | untrusted | -| sqlx.go:28:16:28:24 | untrusted | diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/Sqlx/sqlx.go b/go/ql/test/library-tests/semmle/go/frameworks/SQL/Sqlx/sqlx.go index edc29c4d4eef..e4e8d43395bd 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/SQL/Sqlx/sqlx.go +++ b/go/ql/test/library-tests/semmle/go/frameworks/SQL/Sqlx/sqlx.go @@ -12,19 +12,19 @@ func main() { db := sqlx.DB{} untrusted := getUntrustedString() - db.Select(nil, untrusted) - db.Get(nil, untrusted) - db.MustExec(untrusted) - db.Queryx(untrusted) - db.NamedExec(untrusted, nil) - db.NamedQuery(untrusted, nil) + db.Select(nil, untrusted) // $ querystring=untrusted + db.Get(nil, untrusted) // $ querystring=untrusted + db.MustExec(untrusted) // $ querystring=untrusted + db.Queryx(untrusted) // $ querystring=untrusted + db.NamedExec(untrusted, nil) // $ querystring=untrusted + db.NamedQuery(untrusted, nil) // $ querystring=untrusted tx := sqlx.Tx{} - tx.Select(nil, untrusted) - tx.Get(nil, untrusted) - tx.MustExec(untrusted) - tx.Queryx(untrusted) - tx.NamedExec(untrusted, nil) - tx.NamedQuery(untrusted, nil) + tx.Select(nil, untrusted) // $ querystring=untrusted + tx.Get(nil, untrusted) // $ querystring=untrusted + tx.MustExec(untrusted) // $ querystring=untrusted + tx.Queryx(untrusted) // $ querystring=untrusted + tx.NamedExec(untrusted, nil) // $ querystring=untrusted + tx.NamedQuery(untrusted, nil) // $ querystring=untrusted } diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/Sqlx/sqlx.ql b/go/ql/test/library-tests/semmle/go/frameworks/SQL/Sqlx/sqlx.ql deleted file mode 100644 index 7b56fd974419..000000000000 --- a/go/ql/test/library-tests/semmle/go/frameworks/SQL/Sqlx/sqlx.ql +++ /dev/null @@ -1,4 +0,0 @@ -import go - -from SQL::QueryString qs -select qs diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/bun/QueryString.expected b/go/ql/test/library-tests/semmle/go/frameworks/SQL/bun/QueryString.expected new file mode 100644 index 000000000000..105b7026d0c4 --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/frameworks/SQL/bun/QueryString.expected @@ -0,0 +1,3 @@ +failures +invalidModelRow +testFailures diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/bun/QueryString.ql b/go/ql/test/library-tests/semmle/go/frameworks/SQL/bun/QueryString.ql new file mode 100644 index 000000000000..eeb43a82fadd --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/frameworks/SQL/bun/QueryString.ql @@ -0,0 +1,60 @@ +import go +import semmle.go.dataflow.ExternalFlow +import ModelValidation +import TestUtilities.InlineExpectationsTest + +module SqlTest implements TestSig { + string getARelevantTag() { result = "query" } + + predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "query" and + exists(SQL::Query q, SQL::QueryString qs | qs = q.getAQueryString() | + q.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), + location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and + element = q.toString() and + value = qs.toString() + ) + } +} + +module QueryString implements TestSig { + string getARelevantTag() { result = "querystring" } + + predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "querystring" and + element = "" and + exists(SQL::QueryString qs | not exists(SQL::Query q | qs = q.getAQueryString()) | + qs.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), + location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and + value = qs.toString() + ) + } +} + +module Config implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node n) { n.asExpr() instanceof StringLit } + + predicate isSink(DataFlow::Node n) { + n = any(DataFlow::CallNode cn | cn.getTarget().getName() = "sink").getAnArgument() + } +} + +module Flow = TaintTracking::Global; + +module TaintFlow implements TestSig { + string getARelevantTag() { result = "flowfrom" } + + predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "flowfrom" and + element = "" and + exists(DataFlow::Node fromNode, DataFlow::Node toNode | + toNode + .hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), + location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and + Flow::flow(fromNode, toNode) and + value = fromNode.asExpr().(StringLit).getValue() + ) + } +} + +import MakeTest> diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/bun/bun.go b/go/ql/test/library-tests/semmle/go/frameworks/SQL/bun/bun.go index 8ce4e5b0826b..44a2e2c2fce4 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/SQL/bun/bun.go +++ b/go/ql/test/library-tests/semmle/go/frameworks/SQL/bun/bun.go @@ -22,28 +22,28 @@ func main() { panic(err) } db := bun.NewDB(sqlite, sqlitedialect.New()) - bun.NewRawQuery(db, untrusted) - - db.ExecContext(ctx, untrusted) - db.PrepareContext(ctx, untrusted) - db.QueryContext(ctx, untrusted) - db.QueryRowContext(ctx, untrusted) - - db.Exec(untrusted) - db.NewRaw(untrusted) - db.Prepare(untrusted) - db.Query(untrusted) - db.QueryRow(untrusted) - db.Raw(untrusted) - - db.NewSelect().ColumnExpr(untrusted) - db.NewSelect().DistinctOn(untrusted) - db.NewSelect().For(untrusted) - db.NewSelect().GroupExpr(untrusted) - db.NewSelect().Having(untrusted) - db.NewSelect().ModelTableExpr(untrusted) - db.NewSelect().OrderExpr(untrusted) - db.NewSelect().TableExpr(untrusted) - db.NewSelect().Where(untrusted) - db.NewSelect().WhereOr(untrusted) + bun.NewRawQuery(db, untrusted) // $ querystring=untrusted + + db.ExecContext(ctx, untrusted) // $ querystring=untrusted + db.PrepareContext(ctx, untrusted) // $ querystring=untrusted + db.QueryContext(ctx, untrusted) // $ querystring=untrusted + db.QueryRowContext(ctx, untrusted) // $ querystring=untrusted + + db.Exec(untrusted) // $ querystring=untrusted + db.NewRaw(untrusted) // $ querystring=untrusted + db.Prepare(untrusted) // $ querystring=untrusted + db.Query(untrusted) // $ querystring=untrusted + db.QueryRow(untrusted) // $ querystring=untrusted + db.Raw(untrusted) // $ querystring=untrusted + + db.NewSelect().ColumnExpr(untrusted) // $ querystring=untrusted + db.NewSelect().DistinctOn(untrusted) // $ querystring=untrusted + db.NewSelect().For(untrusted) // $ querystring=untrusted + db.NewSelect().GroupExpr(untrusted) // $ querystring=untrusted + db.NewSelect().Having(untrusted) // $ querystring=untrusted + db.NewSelect().ModelTableExpr(untrusted) // $ querystring=untrusted + db.NewSelect().OrderExpr(untrusted) // $ querystring=untrusted + db.NewSelect().TableExpr(untrusted) // $ querystring=untrusted + db.NewSelect().Where(untrusted) // $ querystring=untrusted + db.NewSelect().WhereOr(untrusted) // $ querystring=untrusted } diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/gogf/QueryString.expected b/go/ql/test/library-tests/semmle/go/frameworks/SQL/gogf/QueryString.expected new file mode 100644 index 000000000000..db33d6d2504a --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/frameworks/SQL/gogf/QueryString.expected @@ -0,0 +1,3 @@ +testFailures +invalidModelRow +failures diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/gogf/QueryString.ql b/go/ql/test/library-tests/semmle/go/frameworks/SQL/gogf/QueryString.ql new file mode 100644 index 000000000000..eeb43a82fadd --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/frameworks/SQL/gogf/QueryString.ql @@ -0,0 +1,60 @@ +import go +import semmle.go.dataflow.ExternalFlow +import ModelValidation +import TestUtilities.InlineExpectationsTest + +module SqlTest implements TestSig { + string getARelevantTag() { result = "query" } + + predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "query" and + exists(SQL::Query q, SQL::QueryString qs | qs = q.getAQueryString() | + q.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), + location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and + element = q.toString() and + value = qs.toString() + ) + } +} + +module QueryString implements TestSig { + string getARelevantTag() { result = "querystring" } + + predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "querystring" and + element = "" and + exists(SQL::QueryString qs | not exists(SQL::Query q | qs = q.getAQueryString()) | + qs.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), + location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and + value = qs.toString() + ) + } +} + +module Config implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node n) { n.asExpr() instanceof StringLit } + + predicate isSink(DataFlow::Node n) { + n = any(DataFlow::CallNode cn | cn.getTarget().getName() = "sink").getAnArgument() + } +} + +module Flow = TaintTracking::Global; + +module TaintFlow implements TestSig { + string getARelevantTag() { result = "flowfrom" } + + predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "flowfrom" and + element = "" and + exists(DataFlow::Node fromNode, DataFlow::Node toNode | + toNode + .hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), + location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and + Flow::flow(fromNode, toNode) and + value = fromNode.asExpr().(StringLit).getValue() + ) + } +} + +import MakeTest> diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/gogf/gogf.expected b/go/ql/test/library-tests/semmle/go/frameworks/SQL/gogf/gogf.expected deleted file mode 100644 index f4e3e4f15b0a..000000000000 --- a/go/ql/test/library-tests/semmle/go/frameworks/SQL/gogf/gogf.expected +++ /dev/null @@ -1,47 +0,0 @@ -| gogf.go:12:9:12:11 | sql | -| gogf.go:13:11:13:13 | sql | -| gogf.go:14:13:14:15 | sql | -| gogf.go:15:13:15:15 | sql | -| gogf.go:16:11:16:13 | sql | -| gogf.go:17:13:17:15 | sql | -| gogf.go:18:12:18:14 | sql | -| gogf.go:19:10:19:12 | sql | -| gogf.go:20:8:20:10 | sql | -| gogf.go:21:17:21:19 | sql | -| gogf.go:22:19:22:21 | sql | -| gogf.go:23:20:23:22 | sql | -| gogf.go:24:23:24:25 | sql | -| gogf.go:25:21:25:23 | sql | -| gogf.go:26:23:26:25 | sql | -| gogf.go:27:22:27:24 | sql | -| gogf.go:28:24:28:26 | sql | -| gogf.go:32:9:32:11 | sql | -| gogf.go:33:11:33:13 | sql | -| gogf.go:34:13:34:15 | sql | -| gogf.go:35:13:35:15 | sql | -| gogf.go:36:11:36:13 | sql | -| gogf.go:37:13:37:15 | sql | -| gogf.go:38:12:38:14 | sql | -| gogf.go:39:10:39:12 | sql | -| gogf.go:40:8:40:10 | sql | -| gogf.go:41:17:41:19 | sql | -| gogf.go:42:23:42:25 | sql | -| gogf.go:43:21:43:23 | sql | -| gogf.go:44:23:44:25 | sql | -| gogf.go:45:22:45:24 | sql | -| gogf.go:46:24:46:26 | sql | -| gogf.go:51:9:51:11 | sql | -| gogf.go:52:11:52:13 | sql | -| gogf.go:53:13:53:15 | sql | -| gogf.go:54:13:54:15 | sql | -| gogf.go:55:11:55:13 | sql | -| gogf.go:56:13:56:15 | sql | -| gogf.go:57:12:57:14 | sql | -| gogf.go:58:10:58:12 | sql | -| gogf.go:59:8:59:10 | sql | -| gogf.go:60:17:60:19 | sql | -| gogf.go:61:23:61:25 | sql | -| gogf.go:62:21:62:23 | sql | -| gogf.go:63:23:63:25 | sql | -| gogf.go:64:22:64:24 | sql | -| gogf.go:65:24:65:26 | sql | diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/gogf/gogf.go b/go/ql/test/library-tests/semmle/go/frameworks/SQL/gogf/gogf.go index d0eceaf862cf..e2db8016cf0d 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/SQL/gogf/gogf.go +++ b/go/ql/test/library-tests/semmle/go/frameworks/SQL/gogf/gogf.go @@ -4,11 +4,13 @@ package main //go:generate depstubber -vendor github.com/gogf/gf/database/gdb DB,Core,TX "" import ( + "context" + "github.com/gogf/gf/database/gdb" "github.com/gogf/gf/frame/g" ) -func gogfCoreTest(sql string, c *gdb.Core) { +func gogfCoreTest(sql string, c *gdb.Core, ctx context.Context) { c.Exec(sql, nil) // $ querystring=sql c.GetAll(sql, nil) // $ querystring=sql c.GetArray(sql, nil) // $ querystring=sql @@ -21,14 +23,14 @@ func gogfCoreTest(sql string, c *gdb.Core) { c.GetScan(nil, sql, nil) // $ querystring=sql c.GetStruct(nil, sql, nil) // $ querystring=sql c.GetStructs(nil, sql, nil) // $ querystring=sql - c.DoCommit(nil, nil, sql, nil) // $ querystring=sql - c.DoExec(nil, nil, sql, nil) // $ querystring=sql - c.DoGetAll(nil, nil, sql, nil) // $ querystring=sql - c.DoQuery(nil, nil, sql, nil) // $ querystring=sql - c.DoPrepare(nil, nil, sql) // $ querystring=sql + c.DoCommit(ctx, nil, sql, nil) // $ querystring=sql + c.DoExec(ctx, nil, sql, nil) // $ querystring=sql + c.DoGetAll(ctx, nil, sql, nil) // $ querystring=sql + c.DoQuery(ctx, nil, sql, nil) // $ querystring=sql + c.DoPrepare(ctx, nil, sql) // $ querystring=sql } -func gogfDbtest(sql string, c gdb.DB) { +func gogfDbtest(sql string, c gdb.DB, ctx context.Context) { c.Exec(sql, nil) // $ querystring=sql c.GetAll(sql, nil) // $ querystring=sql c.GetArray(sql, nil) // $ querystring=sql @@ -39,14 +41,14 @@ func gogfDbtest(sql string, c gdb.DB) { c.Query(sql, nil) // $ querystring=sql c.Raw(sql, nil) // $ querystring=sql c.GetScan(nil, sql, nil) // $ querystring=sql - c.DoCommit(nil, nil, sql, nil) // $ querystring=sql - c.DoExec(nil, nil, sql, nil) // $ querystring=sql - c.DoGetAll(nil, nil, sql, nil) // $ querystring=sql - c.DoQuery(nil, nil, sql, nil) // $ querystring=sql - c.DoPrepare(nil, nil, sql) // $ querystring=sql + c.DoCommit(ctx, nil, sql, nil) // $ querystring=sql + c.DoExec(ctx, nil, sql, nil) // $ querystring=sql + c.DoGetAll(ctx, nil, sql, nil) // $ querystring=sql + c.DoQuery(ctx, nil, sql, nil) // $ querystring=sql + c.DoPrepare(ctx, nil, sql) // $ querystring=sql } -func gogfGTest(sql string) { +func gogfGTest(sql string, ctx context.Context) { c := g.DB("ad") c.Exec(sql, nil) // $ querystring=sql c.GetAll(sql, nil) // $ querystring=sql @@ -58,11 +60,11 @@ func gogfGTest(sql string) { c.Query(sql, nil) // $ querystring=sql c.Raw(sql, nil) // $ querystring=sql c.GetScan(nil, sql, nil) // $ querystring=sql - c.DoCommit(nil, nil, sql, nil) // $ querystring=sql - c.DoExec(nil, nil, sql, nil) // $ querystring=sql - c.DoGetAll(nil, nil, sql, nil) // $ querystring=sql - c.DoQuery(nil, nil, sql, nil) // $ querystring=sql - c.DoPrepare(nil, nil, sql) // $ querystring=sql + c.DoCommit(ctx, nil, sql, nil) // $ querystring=sql + c.DoExec(ctx, nil, sql, nil) // $ querystring=sql + c.DoGetAll(ctx, nil, sql, nil) // $ querystring=sql + c.DoQuery(ctx, nil, sql, nil) // $ querystring=sql + c.DoPrepare(ctx, nil, sql) // $ querystring=sql } func main() { diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/gogf/gogf.ql b/go/ql/test/library-tests/semmle/go/frameworks/SQL/gogf/gogf.ql deleted file mode 100644 index 7b56fd974419..000000000000 --- a/go/ql/test/library-tests/semmle/go/frameworks/SQL/gogf/gogf.ql +++ /dev/null @@ -1,4 +0,0 @@ -import go - -from SQL::QueryString qs -select qs diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/QueryString.expected b/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/QueryString.expected new file mode 100644 index 000000000000..db33d6d2504a --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/QueryString.expected @@ -0,0 +1,3 @@ +testFailures +invalidModelRow +failures diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/QueryString.ql b/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/QueryString.ql new file mode 100644 index 000000000000..eeb43a82fadd --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/QueryString.ql @@ -0,0 +1,60 @@ +import go +import semmle.go.dataflow.ExternalFlow +import ModelValidation +import TestUtilities.InlineExpectationsTest + +module SqlTest implements TestSig { + string getARelevantTag() { result = "query" } + + predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "query" and + exists(SQL::Query q, SQL::QueryString qs | qs = q.getAQueryString() | + q.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), + location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and + element = q.toString() and + value = qs.toString() + ) + } +} + +module QueryString implements TestSig { + string getARelevantTag() { result = "querystring" } + + predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "querystring" and + element = "" and + exists(SQL::QueryString qs | not exists(SQL::Query q | qs = q.getAQueryString()) | + qs.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), + location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and + value = qs.toString() + ) + } +} + +module Config implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node n) { n.asExpr() instanceof StringLit } + + predicate isSink(DataFlow::Node n) { + n = any(DataFlow::CallNode cn | cn.getTarget().getName() = "sink").getAnArgument() + } +} + +module Flow = TaintTracking::Global; + +module TaintFlow implements TestSig { + string getARelevantTag() { result = "flowfrom" } + + predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "flowfrom" and + element = "" and + exists(DataFlow::Node fromNode, DataFlow::Node toNode | + toNode + .hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), + location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and + Flow::flow(fromNode, toNode) and + value = fromNode.asExpr().(StringLit).getValue() + ) + } +} + +import MakeTest> diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/go.mod b/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/go.mod index 1f243775658a..826ed0eb1c05 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/go.mod +++ b/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/go.mod @@ -2,4 +2,4 @@ module main go 1.18 -require github.com/rqlite/gorqlite v0.0.0-20220528150909-c4e99ae96be6 +require github.com/rqlite/gorqlite v0.0.0-20240808172217-12ae7d03ef19 diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/gorqlite.expected b/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/gorqlite.expected deleted file mode 100644 index cbd8166ea5e1..000000000000 --- a/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/gorqlite.expected +++ /dev/null @@ -1,6 +0,0 @@ -| gorqlite.go:11:13:11:16 | sqls | -| gorqlite.go:12:13:12:16 | sqls | -| gorqlite.go:13:13:13:16 | sqls | -| gorqlite.go:14:16:14:18 | sql | -| gorqlite.go:15:16:15:18 | sql | -| gorqlite.go:16:16:16:18 | sql | diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/gorqlite.go b/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/gorqlite.go index 9b60c6684e67..ebd6e5fd9f3b 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/gorqlite.go +++ b/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/gorqlite.go @@ -1,20 +1,49 @@ package main -//go:generate depstubber -vendor github.com/rqlite/gorqlite Connection Open +//go:generate depstubber -vendor github.com/rqlite/gorqlite Connection,ParameterizedStatement Open import ( + "context" + "github.com/rqlite/gorqlite" ) -func gorqlitetest(sql string, sqls []string) { +func gorqlitetest(sql string, sqls []string, param_sql gorqlite.ParameterizedStatement, param_sqls []gorqlite.ParameterizedStatement, ctx context.Context) { conn, _ := gorqlite.Open("dbUrl") - conn.Query(sqls) // $ querystring=sqls - conn.Queue(sqls) // $ querystring=sqls - conn.Write(sqls) // $ querystring=sqls + + conn.Query(sqls) // $ querystring=sqls + conn.Queue(sqls) // $ querystring=sqls + conn.Write(sqls) // $ querystring=sqls + conn.QueryOne(sql) // $ querystring=sql conn.QueueOne(sql) // $ querystring=sql conn.WriteOne(sql) // $ querystring=sql + + conn.QueryParameterized(param_sqls) // $ querystring=param_sqls + conn.QueueParameterized(param_sqls) // $ querystring=param_sqls + conn.WriteParameterized(param_sqls) // $ querystring=param_sqls + + conn.QueryOneParameterized(param_sql) // $ querystring=param_sql + conn.QueueOneParameterized(param_sql) // $ querystring=param_sql + conn.WriteOneParameterized(param_sql) // $ querystring=param_sql + + conn.QueryContext(ctx, sqls) // $ querystring=sqls + conn.QueueContext(ctx, sqls) // $ querystring=sqls + conn.WriteContext(ctx, sqls) // $ querystring=sqls + + conn.QueryOneContext(ctx, sql) // $ querystring=sql + conn.QueueOneContext(ctx, sql) // $ querystring=sql + conn.WriteOneContext(ctx, sql) // $ querystring=sql + + conn.QueryParameterizedContext(ctx, param_sqls) // $ querystring=param_sqls + conn.QueueParameterizedContext(ctx, param_sqls) // $ querystring=param_sqls + conn.WriteParameterizedContext(ctx, param_sqls) // $ querystring=param_sqls + + conn.QueryOneParameterizedContext(ctx, param_sql) // $ querystring=param_sql + conn.QueueOneParameterizedContext(ctx, param_sql) // $ querystring=param_sql + conn.WriteOneParameterizedContext(ctx, param_sql) // $ querystring=param_sql } + func main() { return } diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/gorqlite.ql b/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/gorqlite.ql deleted file mode 100644 index 7b56fd974419..000000000000 --- a/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/gorqlite.ql +++ /dev/null @@ -1,4 +0,0 @@ -import go - -from SQL::QueryString qs -select qs diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/vendor/github.com/rqlite/gorqlite/stub.go b/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/vendor/github.com/rqlite/gorqlite/stub.go index f6f4ca18ec12..0572097582e0 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/vendor/github.com/rqlite/gorqlite/stub.go +++ b/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/vendor/github.com/rqlite/gorqlite/stub.go @@ -2,11 +2,15 @@ // This is a simple stub for github.com/rqlite/gorqlite, strictly for use in testing. // See the LICENSE file for information about the licensing of the original library. -// Source: github.com/rqlite/gorqlite (exports: Connection; functions: Open) +// Source: github.com/rqlite/gorqlite (exports: Connection,ParameterizedStatement; functions: Open) // Package gorqlite is a stub of github.com/rqlite/gorqlite, generated by depstubber. package gorqlite +import ( + context "context" +) + type Connection struct { ID string } @@ -29,19 +33,83 @@ func (_ *Connection) Query(_ []string) ([]QueryResult, error) { return nil, nil } +func (_ *Connection) QueryContext(_ context.Context, _ []string) ([]QueryResult, error) { + return nil, nil +} + func (_ *Connection) QueryOne(_ string) (QueryResult, error) { return QueryResult{}, nil } +func (_ *Connection) QueryOneContext(_ context.Context, _ string) (QueryResult, error) { + return QueryResult{}, nil +} + +func (_ *Connection) QueryOneParameterized(_ ParameterizedStatement) (QueryResult, error) { + return QueryResult{}, nil +} + +func (_ *Connection) QueryOneParameterizedContext(_ context.Context, _ ParameterizedStatement) (QueryResult, error) { + return QueryResult{}, nil +} + +func (_ *Connection) QueryParameterized(_ []ParameterizedStatement) ([]QueryResult, error) { + return nil, nil +} + +func (_ *Connection) QueryParameterizedContext(_ context.Context, _ []ParameterizedStatement) ([]QueryResult, error) { + return nil, nil +} + func (_ *Connection) Queue(_ []string) (int64, error) { return 0, nil } +func (_ *Connection) QueueContext(_ context.Context, _ []string) (int64, error) { + return 0, nil +} + func (_ *Connection) QueueOne(_ string) (int64, error) { return 0, nil } -func (_ *Connection) SetConsistencyLevel(_ string) error { +func (_ *Connection) QueueOneContext(_ context.Context, _ string) (int64, error) { + return 0, nil +} + +func (_ *Connection) QueueOneParameterized(_ ParameterizedStatement) (int64, error) { + return 0, nil +} + +func (_ *Connection) QueueOneParameterizedContext(_ context.Context, _ ParameterizedStatement) (int64, error) { + return 0, nil +} + +func (_ *Connection) QueueParameterized(_ []ParameterizedStatement) (int64, error) { + return 0, nil +} + +func (_ *Connection) QueueParameterizedContext(_ context.Context, _ []ParameterizedStatement) (int64, error) { + return 0, nil +} + +func (_ *Connection) Request(_ []string) ([]RequestResult, error) { + return nil, nil +} + +func (_ *Connection) RequestContext(_ context.Context, _ []string) ([]RequestResult, error) { + return nil, nil +} + +func (_ *Connection) RequestParameterized(_ []ParameterizedStatement) ([]RequestResult, error) { + return nil, nil +} + +func (_ *Connection) RequestParameterizedContext(_ context.Context, _ []ParameterizedStatement) ([]RequestResult, error) { + return nil, nil +} + +func (_ *Connection) SetConsistencyLevel(_ interface{}) error { return nil } @@ -53,12 +121,41 @@ func (_ *Connection) Write(_ []string) ([]WriteResult, error) { return nil, nil } +func (_ *Connection) WriteContext(_ context.Context, _ []string) ([]WriteResult, error) { + return nil, nil +} + func (_ *Connection) WriteOne(_ string) (WriteResult, error) { return WriteResult{}, nil } -func Open(_ string) (Connection, error) { - return Connection{}, nil +func (_ *Connection) WriteOneContext(_ context.Context, _ string) (WriteResult, error) { + return WriteResult{}, nil +} + +func (_ *Connection) WriteOneParameterized(_ ParameterizedStatement) (WriteResult, error) { + return WriteResult{}, nil +} + +func (_ *Connection) WriteOneParameterizedContext(_ context.Context, _ ParameterizedStatement) (WriteResult, error) { + return WriteResult{}, nil +} + +func (_ *Connection) WriteParameterized(_ []ParameterizedStatement) ([]WriteResult, error) { + return nil, nil +} + +func (_ *Connection) WriteParameterizedContext(_ context.Context, _ []ParameterizedStatement) ([]WriteResult, error) { + return nil, nil +} + +func Open(_ string) (*Connection, error) { + return nil, nil +} + +type ParameterizedStatement struct { + Query string + Arguments []interface{} } type QueryResult struct { @@ -90,10 +187,20 @@ func (_ *QueryResult) Scan(_ ...interface{}) error { return nil } +func (_ *QueryResult) Slice() ([]interface{}, error) { + return nil, nil +} + func (_ *QueryResult) Types() []string { return nil } +type RequestResult struct { + Err error + Query *QueryResult + Write *WriteResult +} + type WriteResult struct { Err error Timing float64 diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/vendor/modules.txt b/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/vendor/modules.txt index f5e5b9989ede..dafb7c6d1a98 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/vendor/modules.txt +++ b/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/vendor/modules.txt @@ -1,3 +1,3 @@ -# github.com/rqlite/gorqlite v0.0.0-20220528150909-c4e99ae96be6 +# github.com/rqlite/gorqlite v0.0.0-20240808172217-12ae7d03ef19 ## explicit github.com/rqlite/gorqlite diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/squirrel.go b/go/ql/test/library-tests/semmle/go/frameworks/SQL/squirrel.go index 15b687c7ad16..d0350643bb06 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/SQL/squirrel.go +++ b/go/ql/test/library-tests/semmle/go/frameworks/SQL/squirrel.go @@ -1,6 +1,6 @@ package main -//go:generate depstubber -vendor github.com/Masterminds/squirrel DeleteBuilder,InsertBuilder,SelectBuilder,UpdateBuilder Delete,Expr,Insert,Select,Update +//go:generate depstubber -vendor github.com/Masterminds/squirrel DeleteBuilder,Eq,InsertBuilder,SelectBuilder,UpdateBuilder Delete,Expr,Insert,Select,Update import ( "github.com/Masterminds/squirrel" @@ -10,38 +10,44 @@ func squirrelTest(querypart string) { squirrel.Expr(querypart) // $ querystring=querypart deleteBuilder := squirrel.Delete(querypart) // $ querystring=querypart deleteBuilder.From(querypart) // $ querystring=querypart - deleteBuilder.OrderBy(querypart) // $ querystring=[]type{args} + deleteBuilder.OrderBy(querypart) // $ querystring=querypart deleteBuilder.Prefix(querypart) // $ querystring=querypart deleteBuilder.Suffix(querypart) // $ querystring=querypart deleteBuilder.Where(querypart) // $ querystring=querypart insertBuilder := squirrel.Insert(querypart) // $ querystring=querypart - insertBuilder.Columns(querypart) // $ querystring=[]type{args} - insertBuilder.Options(querypart) // $ querystring=[]type{args} + insertBuilder.Columns(querypart) // $ querystring=querypart + insertBuilder.Options(querypart) // $ querystring=querypart insertBuilder.Prefix(querypart) // $ querystring=querypart insertBuilder.Suffix(querypart) // $ querystring=querypart insertBuilder.Into(querypart) // $ querystring=querypart - selectBuilder := squirrel.Select(querypart) // $ querystring=[]type{args} - selectBuilder.Columns(querypart) // $ querystring=[]type{args} + selectBuilder := squirrel.Select(querypart) // $ querystring=querypart + selectBuilder.Columns(querypart) // $ querystring=querypart selectBuilder.From(querypart) // $ querystring=querypart - selectBuilder.Options(querypart) // $ querystring=[]type{args} - selectBuilder.OrderBy(querypart) // $ querystring=[]type{args} + selectBuilder.Options(querypart) // $ querystring=querypart + selectBuilder.OrderBy(querypart) // $ querystring=querypart selectBuilder.Prefix(querypart) // $ querystring=querypart selectBuilder.Suffix(querypart) // $ querystring=querypart selectBuilder.Where(querypart) // $ querystring=querypart selectBuilder.CrossJoin(querypart) // $ querystring=querypart - selectBuilder.GroupBy(querypart) // $ querystring=[]type{args} + selectBuilder.GroupBy(querypart) // $ querystring=querypart selectBuilder.InnerJoin(querypart) // $ querystring=querypart selectBuilder.LeftJoin(querypart) // $ querystring=querypart selectBuilder.RightJoin(querypart) // $ querystring=querypart updateBuilder := squirrel.Update(querypart) // $ querystring=querypart updateBuilder.From(querypart) // $ querystring=querypart - updateBuilder.OrderBy(querypart) // $ querystring=[]type{args} + updateBuilder.OrderBy(querypart) // $ querystring=querypart updateBuilder.Prefix(querypart) // $ querystring=querypart updateBuilder.Suffix(querypart) // $ querystring=querypart updateBuilder.Where(querypart) // $ querystring=querypart updateBuilder.Set(querypart, "") // $ querystring=querypart updateBuilder.Table(querypart) // $ querystring=querypart + + // safe + wrapped := squirrel.Eq{"id": querypart} + deleteBuilder.Where(wrapped) + selectBuilder.Where(wrapped) + updateBuilder.Where(wrapped) } diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/vendor/github.com/Masterminds/squirrel/stub.go b/go/ql/test/library-tests/semmle/go/frameworks/SQL/vendor/github.com/Masterminds/squirrel/stub.go index 96a30e49d4ec..1a9e5ca0e9b9 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/SQL/vendor/github.com/Masterminds/squirrel/stub.go +++ b/go/ql/test/library-tests/semmle/go/frameworks/SQL/vendor/github.com/Masterminds/squirrel/stub.go @@ -2,7 +2,7 @@ // This is a simple stub for github.com/Masterminds/squirrel, strictly for use in testing. // See the LICENSE file for information about the licensing of the original library. -// Source: github.com/Masterminds/squirrel (exports: DeleteBuilder,InsertBuilder,SelectBuilder,UpdateBuilder; functions: Delete,Expr,Insert,Select,Update) +// Source: github.com/Masterminds/squirrel (exports: DeleteBuilder,Eq,InsertBuilder,SelectBuilder,UpdateBuilder; functions: Delete,Expr,Insert,Select,Update) // Package squirrel is a stub of github.com/Masterminds/squirrel, generated by depstubber. package squirrel @@ -99,6 +99,12 @@ func (_ DeleteBuilder) Where(_ interface{}, _ ...interface{}) DeleteBuilder { return DeleteBuilder{} } +type Eq map[string]interface{} + +func (_ Eq) ToSql() (string, []interface{}, error) { + return "", nil, nil +} + func Expr(_ string, _ ...interface{}) Sqlizer { return nil } diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/xorm.go b/go/ql/test/library-tests/semmle/go/frameworks/SQL/xorm.go index 6b4dbb116eec..f63b33a0e09b 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/SQL/xorm.go +++ b/go/ql/test/library-tests/semmle/go/frameworks/SQL/xorm.go @@ -10,68 +10,73 @@ import ( func xormtest() { query := "UntrustedString" + arg := "arg" engine1 := xorm1.Engine{} - engine1.Query(query) // $ querystring=query - engine1.QueryString(query) // $ querystring=query - engine1.QueryInterface(query) // $ querystring=query - engine1.SQL(query) // $ querystring=query - engine1.Where(query) // $ querystring=query - engine1.Alias(query) // $ querystring=query - engine1.NotIn(query) // $ querystring=query - engine1.In(query) // $ querystring=query - engine1.Select(query) // $ querystring=query - engine1.SetExpr(query, nil) // $ querystring=query - engine1.OrderBy(query) // $ querystring=query - engine1.Having(query) // $ querystring=query - engine1.GroupBy(query) // $ querystring=query + engine1.Query(query, arg) // $ querystring=query + engine1.Exec(query, arg) // $ querystring=query + engine1.QueryString(query, arg) // $ querystring=query + engine1.QueryInterface(query, arg) // $ querystring=query + engine1.SQL(query) // $ querystring=query + engine1.Where(query) // $ querystring=query + engine1.Alias(query) // $ querystring=query + engine1.NotIn(query) // $ querystring=query + engine1.In(query) // $ querystring=query + engine1.Select(query) // $ querystring=query + engine1.SetExpr(query, nil) // $ querystring=query + engine1.OrderBy(query) // $ querystring=query + engine1.Having(query) // $ querystring=query + engine1.GroupBy(query) // $ querystring=query engine2 := xorm2.Engine{} - engine2.Query(query) // $ querystring=query - engine2.QueryString(query) // $ querystring=query - engine2.QueryInterface(query) // $ querystring=query - engine2.SQL(query) // $ querystring=query - engine2.Where(query) // $ querystring=query - engine2.Alias(query) // $ querystring=query - engine2.NotIn(query) // $ querystring=query - engine2.In(query) // $ querystring=query - engine2.Select(query) // $ querystring=query - engine2.SetExpr(query, nil) // $ querystring=query - engine2.OrderBy(query) // $ querystring=query - engine2.Having(query) // $ querystring=query - engine2.GroupBy(query) // $ querystring=query + engine2.Query(query, arg) // $ querystring=query + engine2.Exec(query, arg) // $ querystring=query + engine2.QueryString(query, arg) // $ querystring=query + engine2.QueryInterface(query, arg) // $ querystring=query + engine2.SQL(query) // $ querystring=query + engine2.Where(query) // $ querystring=query + engine2.Alias(query) // $ querystring=query + engine2.NotIn(query) // $ querystring=query + engine2.In(query) // $ querystring=query + engine2.Select(query) // $ querystring=query + engine2.SetExpr(query, nil) // $ querystring=query + engine2.OrderBy(query) // $ querystring=query + engine2.Having(query) // $ querystring=query + engine2.GroupBy(query) // $ querystring=query session1 := xorm1.Session{} - session1.Query(query) // $ querystring=query - session1.QueryString(query) // $ querystring=query - session1.QueryInterface(query) // $ querystring=query - session1.SQL(query) // $ querystring=query - session1.Where(query) // $ querystring=query - session1.Alias(query) // $ querystring=query - session1.NotIn(query) // $ querystring=query - session1.In(query) // $ querystring=query - session1.Select(query) // $ querystring=query - session1.SetExpr(query, nil) // $ querystring=query - session1.OrderBy(query) // $ querystring=query - session1.Having(query) // $ querystring=query - session1.GroupBy(query) // $ querystring=query - session1.And(query) // $ querystring=query - session1.Or(query) // $ querystring=query + session1.Query(query, arg) // $ querystring=query + session1.Exec(query, arg) // $ querystring=query + session1.QueryString(query, arg) // $ querystring=query + session1.QueryInterface(query, arg) // $ querystring=query + session1.SQL(query) // $ querystring=query + session1.Where(query) // $ querystring=query + session1.Alias(query) // $ querystring=query + session1.NotIn(query) // $ querystring=query + session1.In(query) // $ querystring=query + session1.Select(query) // $ querystring=query + session1.SetExpr(query, nil) // $ querystring=query + session1.OrderBy(query) // $ querystring=query + session1.Having(query) // $ querystring=query + session1.GroupBy(query) // $ querystring=query + session1.And(query) // $ querystring=query + session1.Or(query) // $ querystring=query session2 := xorm2.Session{} - session2.Query(query) // $ querystring=query - session2.QueryString(query) // $ querystring=query - session2.QueryInterface(query) // $ querystring=query - session2.SQL(query) // $ querystring=query - session2.Where(query) // $ querystring=query - session2.Alias(query) // $ querystring=query - session2.NotIn(query) // $ querystring=query - session2.In(query) // $ querystring=query - session2.Select(query) // $ querystring=query - session2.SetExpr(query, nil) // $ querystring=query - session2.OrderBy(query) // $ querystring=query - session2.Having(query) // $ querystring=query - session2.GroupBy(query) // $ querystring=query - session2.And(query) // $ querystring=query - session2.Or(query) // $ querystring=query + session2.Query(query, arg) // $ querystring=query + session2.Exec(query, arg) // $ querystring=query + session2.QueryString(query, arg) // $ querystring=query + session2.QueryInterface(query, arg) // $ querystring=query + session2.SQL(query) // $ querystring=query + session2.Where(query) // $ querystring=query + session2.Alias(query) // $ querystring=query + session2.NotIn(query) // $ querystring=query + session2.In(query) // $ querystring=query + session2.Select(query) // $ querystring=query + session2.SetExpr(query, nil) // $ querystring=query + session2.OrderBy(query) // $ querystring=query + session2.Having(query) // $ querystring=query + session2.GroupBy(query) // $ querystring=query + session2.And(query) // $ querystring=query + session2.Or(query) // $ querystring=query } diff --git a/go/ql/test/library-tests/semmle/go/frameworks/XNetHtml/SqlInjection.expected b/go/ql/test/library-tests/semmle/go/frameworks/XNetHtml/SqlInjection.expected index c28b1058e7c7..8b2f05c297f8 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/XNetHtml/SqlInjection.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/XNetHtml/SqlInjection.expected @@ -1,11 +1,12 @@ #select | test.go:57:11:57:41 | call to EscapeString | test.go:56:2:56:42 | ... := ...[0] | test.go:57:11:57:41 | call to EscapeString | This query depends on a $@. | test.go:56:2:56:42 | ... := ...[0] | user-provided value | edges -| test.go:56:2:56:42 | ... := ...[0] | test.go:57:29:57:40 | selection of Value | provenance | Src:MaD:1 | -| test.go:57:29:57:40 | selection of Value | test.go:57:11:57:41 | call to EscapeString | provenance | MaD:2 | +| test.go:56:2:56:42 | ... := ...[0] | test.go:57:29:57:40 | selection of Value | provenance | Src:MaD:2 | +| test.go:57:29:57:40 | selection of Value | test.go:57:11:57:41 | call to EscapeString | provenance | MaD:3 Sink:MaD:1 | models -| 1 | Source: net/http; Request; true; Cookie; ; ; ReturnValue[0]; remote; manual | -| 2 | Summary: golang.org/x/net/html; ; false; EscapeString; ; ; Argument[0]; ReturnValue; taint; manual | +| 1 | Sink: database/sql; DB; true; Query; ; ; Argument[0]; sql-injection; manual | +| 2 | Source: net/http; Request; true; Cookie; ; ; ReturnValue[0]; remote; manual | +| 3 | Summary: golang.org/x/net/html; ; false; EscapeString; ; ; Argument[0]; ReturnValue; taint; manual | nodes | test.go:56:2:56:42 | ... := ...[0] | semmle.label | ... := ...[0] | | test.go:57:11:57:41 | call to EscapeString | semmle.label | call to EscapeString | diff --git a/go/ql/test/query-tests/Security/CWE-089/SqlInjection.expected b/go/ql/test/query-tests/Security/CWE-089/SqlInjection.expected index 79d8809e19f9..1ce8c3d1dcf6 100644 --- a/go/ql/test/query-tests/Security/CWE-089/SqlInjection.expected +++ b/go/ql/test/query-tests/Security/CWE-089/SqlInjection.expected @@ -25,53 +25,53 @@ | mongoDB.go:80:22:80:27 | filter | mongoDB.go:40:20:40:30 | call to Referer | mongoDB.go:80:22:80:27 | filter | This query depends on a $@. | mongoDB.go:40:20:40:30 | call to Referer | user-provided value | | mongoDB.go:81:18:81:25 | pipeline | mongoDB.go:40:20:40:30 | call to Referer | mongoDB.go:81:18:81:25 | pipeline | This query depends on a $@. | mongoDB.go:40:20:40:30 | call to Referer | user-provided value | edges -| SqlInjection.go:10:7:11:30 | []type{args} [array] | SqlInjection.go:10:7:11:30 | call to Sprintf | provenance | MaD:7 | -| SqlInjection.go:10:7:11:30 | call to Sprintf | SqlInjection.go:12:11:12:11 | q | provenance | | -| SqlInjection.go:11:3:11:9 | selection of URL | SqlInjection.go:11:3:11:17 | call to Query | provenance | Src:MaD:5 MaD:10 | +| SqlInjection.go:10:7:11:30 | []type{args} [array] | SqlInjection.go:10:7:11:30 | call to Sprintf | provenance | MaD:23 | +| SqlInjection.go:10:7:11:30 | call to Sprintf | SqlInjection.go:12:11:12:11 | q | provenance | Sink:MaD:1 | +| SqlInjection.go:11:3:11:9 | selection of URL | SqlInjection.go:11:3:11:17 | call to Query | provenance | Src:MaD:21 MaD:26 | | SqlInjection.go:11:3:11:17 | call to Query | SqlInjection.go:11:3:11:29 | index expression | provenance | | | SqlInjection.go:11:3:11:29 | index expression | SqlInjection.go:10:7:11:30 | []type{args} [array] | provenance | | | SqlInjection.go:11:3:11:29 | index expression | SqlInjection.go:10:7:11:30 | call to Sprintf | provenance | FunctionModel | | issue48.go:17:2:17:33 | ... := ...[0] | issue48.go:18:17:18:17 | b | provenance | | -| issue48.go:17:25:17:32 | selection of Body | issue48.go:17:2:17:33 | ... := ...[0] | provenance | Src:MaD:1 MaD:8 | -| issue48.go:18:17:18:17 | b | issue48.go:18:20:18:39 | &... | provenance | MaD:6 | +| issue48.go:17:25:17:32 | selection of Body | issue48.go:17:2:17:33 | ... := ...[0] | provenance | Src:MaD:17 MaD:24 | +| issue48.go:18:17:18:17 | b | issue48.go:18:20:18:39 | &... | provenance | MaD:22 | | issue48.go:18:20:18:39 | &... | issue48.go:21:3:21:33 | index expression | provenance | | -| issue48.go:20:8:21:34 | []type{args} [array] | issue48.go:20:8:21:34 | call to Sprintf | provenance | MaD:7 | -| issue48.go:20:8:21:34 | call to Sprintf | issue48.go:22:11:22:12 | q3 | provenance | | +| issue48.go:20:8:21:34 | []type{args} [array] | issue48.go:20:8:21:34 | call to Sprintf | provenance | MaD:23 | +| issue48.go:20:8:21:34 | call to Sprintf | issue48.go:22:11:22:12 | q3 | provenance | Sink:MaD:1 | | issue48.go:21:3:21:33 | index expression | issue48.go:20:8:21:34 | []type{args} [array] | provenance | | | issue48.go:21:3:21:33 | index expression | issue48.go:20:8:21:34 | call to Sprintf | provenance | FunctionModel | | issue48.go:27:2:27:34 | ... := ...[0] | issue48.go:28:17:28:18 | b2 | provenance | | -| issue48.go:27:26:27:33 | selection of Body | issue48.go:27:2:27:34 | ... := ...[0] | provenance | Src:MaD:1 MaD:8 | -| issue48.go:28:17:28:18 | b2 | issue48.go:28:21:28:41 | &... | provenance | MaD:6 | +| issue48.go:27:26:27:33 | selection of Body | issue48.go:27:2:27:34 | ... := ...[0] | provenance | Src:MaD:17 MaD:24 | +| issue48.go:28:17:28:18 | b2 | issue48.go:28:21:28:41 | &... | provenance | MaD:22 | | issue48.go:28:21:28:41 | &... | issue48.go:31:3:31:31 | selection of Category | provenance | | -| issue48.go:30:8:31:32 | []type{args} [array] | issue48.go:30:8:31:32 | call to Sprintf | provenance | MaD:7 | -| issue48.go:30:8:31:32 | call to Sprintf | issue48.go:32:11:32:12 | q4 | provenance | | +| issue48.go:30:8:31:32 | []type{args} [array] | issue48.go:30:8:31:32 | call to Sprintf | provenance | MaD:23 | +| issue48.go:30:8:31:32 | call to Sprintf | issue48.go:32:11:32:12 | q4 | provenance | Sink:MaD:1 | | issue48.go:31:3:31:31 | selection of Category | issue48.go:30:8:31:32 | []type{args} [array] | provenance | | | issue48.go:31:3:31:31 | selection of Category | issue48.go:30:8:31:32 | call to Sprintf | provenance | FunctionModel | -| issue48.go:37:17:37:50 | type conversion | issue48.go:37:53:37:73 | &... | provenance | MaD:6 | -| issue48.go:37:24:37:30 | selection of URL | issue48.go:37:24:37:38 | call to Query | provenance | Src:MaD:5 MaD:10 | +| issue48.go:37:17:37:50 | type conversion | issue48.go:37:53:37:73 | &... | provenance | MaD:22 | +| issue48.go:37:24:37:30 | selection of URL | issue48.go:37:24:37:38 | call to Query | provenance | Src:MaD:21 MaD:26 | | issue48.go:37:24:37:38 | call to Query | issue48.go:37:17:37:50 | type conversion | provenance | | | issue48.go:37:53:37:73 | &... | issue48.go:40:3:40:31 | selection of Category | provenance | | -| issue48.go:39:8:40:32 | []type{args} [array] | issue48.go:39:8:40:32 | call to Sprintf | provenance | MaD:7 | -| issue48.go:39:8:40:32 | call to Sprintf | issue48.go:41:11:41:12 | q5 | provenance | | +| issue48.go:39:8:40:32 | []type{args} [array] | issue48.go:39:8:40:32 | call to Sprintf | provenance | MaD:23 | +| issue48.go:39:8:40:32 | call to Sprintf | issue48.go:41:11:41:12 | q5 | provenance | Sink:MaD:1 | | issue48.go:40:3:40:31 | selection of Category | issue48.go:39:8:40:32 | []type{args} [array] | provenance | | | issue48.go:40:3:40:31 | selection of Category | issue48.go:39:8:40:32 | call to Sprintf | provenance | FunctionModel | -| main.go:11:11:11:16 | selection of Form | main.go:11:11:11:28 | index expression | provenance | Src:MaD:2 | -| main.go:15:11:15:84 | []type{args} [array] | main.go:15:11:15:84 | call to Sprintf | provenance | MaD:7 | -| main.go:15:63:15:67 | selection of URL | main.go:15:63:15:75 | call to Query | provenance | Src:MaD:5 MaD:10 | +| main.go:11:11:11:16 | selection of Form | main.go:11:11:11:28 | index expression | provenance | Src:MaD:18 Sink:MaD:1 | +| main.go:15:11:15:84 | []type{args} [array] | main.go:15:11:15:84 | call to Sprintf | provenance | MaD:23 Sink:MaD:2 | +| main.go:15:63:15:67 | selection of URL | main.go:15:63:15:75 | call to Query | provenance | Src:MaD:21 MaD:26 | | main.go:15:63:15:75 | call to Query | main.go:15:63:15:83 | index expression | provenance | | | main.go:15:63:15:83 | index expression | main.go:15:11:15:84 | []type{args} [array] | provenance | | -| main.go:15:63:15:83 | index expression | main.go:15:11:15:84 | call to Sprintf | provenance | FunctionModel | -| main.go:16:11:16:85 | []type{args} [array] | main.go:16:11:16:85 | call to Sprintf | provenance | MaD:7 | -| main.go:16:63:16:70 | selection of Header | main.go:16:63:16:84 | call to Get | provenance | Src:MaD:3 MaD:9 | +| main.go:15:63:15:83 | index expression | main.go:15:11:15:84 | call to Sprintf | provenance | FunctionModel Sink:MaD:2 | +| main.go:16:11:16:85 | []type{args} [array] | main.go:16:11:16:85 | call to Sprintf | provenance | MaD:23 Sink:MaD:2 | +| main.go:16:63:16:70 | selection of Header | main.go:16:63:16:84 | call to Get | provenance | Src:MaD:19 MaD:25 | | main.go:16:63:16:84 | call to Get | main.go:16:11:16:85 | []type{args} [array] | provenance | | -| main.go:16:63:16:84 | call to Get | main.go:16:11:16:85 | call to Sprintf | provenance | FunctionModel | +| main.go:16:63:16:84 | call to Get | main.go:16:11:16:85 | call to Sprintf | provenance | FunctionModel Sink:MaD:2 | | main.go:28:17:31:2 | &... [pointer, Category] | main.go:34:3:34:13 | RequestData [pointer, Category] | provenance | | | main.go:28:18:31:2 | struct literal [Category] | main.go:28:17:31:2 | &... [pointer, Category] | provenance | | -| main.go:30:13:30:19 | selection of URL | main.go:30:13:30:27 | call to Query | provenance | Src:MaD:5 MaD:10 | +| main.go:30:13:30:19 | selection of URL | main.go:30:13:30:27 | call to Query | provenance | Src:MaD:21 MaD:26 | | main.go:30:13:30:27 | call to Query | main.go:30:13:30:39 | index expression | provenance | | | main.go:30:13:30:39 | index expression | main.go:28:18:31:2 | struct literal [Category] | provenance | | -| main.go:33:7:34:23 | []type{args} [array] | main.go:33:7:34:23 | call to Sprintf | provenance | MaD:7 | -| main.go:33:7:34:23 | call to Sprintf | main.go:35:11:35:11 | q | provenance | | +| main.go:33:7:34:23 | []type{args} [array] | main.go:33:7:34:23 | call to Sprintf | provenance | MaD:23 | +| main.go:33:7:34:23 | call to Sprintf | main.go:35:11:35:11 | q | provenance | Sink:MaD:1 | | main.go:34:3:34:13 | RequestData [pointer, Category] | main.go:34:3:34:13 | implicit dereference [Category] | provenance | | | main.go:34:3:34:13 | implicit dereference [Category] | main.go:34:3:34:22 | selection of Category | provenance | | | main.go:34:3:34:22 | selection of Category | main.go:33:7:34:23 | []type{args} [array] | provenance | | @@ -80,11 +80,11 @@ edges | main.go:39:2:39:12 | definition of RequestData [pointer, Category] | main.go:43:3:43:13 | RequestData [pointer, Category] | provenance | | | main.go:40:2:40:12 | RequestData [pointer, Category] | main.go:40:2:40:12 | implicit dereference [Category] | provenance | | | main.go:40:2:40:12 | implicit dereference [Category] | main.go:39:2:39:12 | definition of RequestData [pointer, Category] | provenance | | -| main.go:40:25:40:31 | selection of URL | main.go:40:25:40:39 | call to Query | provenance | Src:MaD:5 MaD:10 | +| main.go:40:25:40:31 | selection of URL | main.go:40:25:40:39 | call to Query | provenance | Src:MaD:21 MaD:26 | | main.go:40:25:40:39 | call to Query | main.go:40:25:40:51 | index expression | provenance | | | main.go:40:25:40:51 | index expression | main.go:40:2:40:12 | implicit dereference [Category] | provenance | | -| main.go:42:7:43:23 | []type{args} [array] | main.go:42:7:43:23 | call to Sprintf | provenance | MaD:7 | -| main.go:42:7:43:23 | call to Sprintf | main.go:44:11:44:11 | q | provenance | | +| main.go:42:7:43:23 | []type{args} [array] | main.go:42:7:43:23 | call to Sprintf | provenance | MaD:23 | +| main.go:42:7:43:23 | call to Sprintf | main.go:44:11:44:11 | q | provenance | Sink:MaD:1 | | main.go:43:3:43:13 | RequestData [pointer, Category] | main.go:43:3:43:13 | implicit dereference [Category] | provenance | | | main.go:43:3:43:13 | implicit dereference [Category] | main.go:43:3:43:22 | selection of Category | provenance | | | main.go:43:3:43:22 | selection of Category | main.go:42:7:43:23 | []type{args} [array] | provenance | | @@ -93,11 +93,11 @@ edges | main.go:48:2:48:12 | definition of RequestData [pointer, Category] | main.go:52:3:52:13 | RequestData [pointer, Category] | provenance | | | main.go:49:3:49:14 | star expression [Category] | main.go:48:2:48:12 | definition of RequestData [pointer, Category] | provenance | | | main.go:49:4:49:14 | RequestData [pointer, Category] | main.go:49:3:49:14 | star expression [Category] | provenance | | -| main.go:49:28:49:34 | selection of URL | main.go:49:28:49:42 | call to Query | provenance | Src:MaD:5 MaD:10 | +| main.go:49:28:49:34 | selection of URL | main.go:49:28:49:42 | call to Query | provenance | Src:MaD:21 MaD:26 | | main.go:49:28:49:42 | call to Query | main.go:49:28:49:54 | index expression | provenance | | | main.go:49:28:49:54 | index expression | main.go:49:3:49:14 | star expression [Category] | provenance | | -| main.go:51:7:52:23 | []type{args} [array] | main.go:51:7:52:23 | call to Sprintf | provenance | MaD:7 | -| main.go:51:7:52:23 | call to Sprintf | main.go:53:11:53:11 | q | provenance | | +| main.go:51:7:52:23 | []type{args} [array] | main.go:51:7:52:23 | call to Sprintf | provenance | MaD:23 | +| main.go:51:7:52:23 | call to Sprintf | main.go:53:11:53:11 | q | provenance | Sink:MaD:1 | | main.go:52:3:52:13 | RequestData [pointer, Category] | main.go:52:3:52:13 | implicit dereference [Category] | provenance | | | main.go:52:3:52:13 | implicit dereference [Category] | main.go:52:3:52:22 | selection of Category | provenance | | | main.go:52:3:52:22 | selection of Category | main.go:51:7:52:23 | []type{args} [array] | provenance | | @@ -106,44 +106,60 @@ edges | main.go:57:2:57:12 | definition of RequestData [pointer, Category] | main.go:61:5:61:15 | RequestData [pointer, Category] | provenance | | | main.go:58:3:58:14 | star expression [Category] | main.go:57:2:57:12 | definition of RequestData [pointer, Category] | provenance | | | main.go:58:4:58:14 | RequestData [pointer, Category] | main.go:58:3:58:14 | star expression [Category] | provenance | | -| main.go:58:28:58:34 | selection of URL | main.go:58:28:58:42 | call to Query | provenance | Src:MaD:5 MaD:10 | +| main.go:58:28:58:34 | selection of URL | main.go:58:28:58:42 | call to Query | provenance | Src:MaD:21 MaD:26 | | main.go:58:28:58:42 | call to Query | main.go:58:28:58:54 | index expression | provenance | | | main.go:58:28:58:54 | index expression | main.go:58:3:58:14 | star expression [Category] | provenance | | -| main.go:60:7:61:26 | []type{args} [array] | main.go:60:7:61:26 | call to Sprintf | provenance | MaD:7 | -| main.go:60:7:61:26 | call to Sprintf | main.go:62:11:62:11 | q | provenance | | +| main.go:60:7:61:26 | []type{args} [array] | main.go:60:7:61:26 | call to Sprintf | provenance | MaD:23 | +| main.go:60:7:61:26 | call to Sprintf | main.go:62:11:62:11 | q | provenance | Sink:MaD:1 | | main.go:61:3:61:25 | selection of Category | main.go:60:7:61:26 | []type{args} [array] | provenance | | | main.go:61:3:61:25 | selection of Category | main.go:60:7:61:26 | call to Sprintf | provenance | FunctionModel | | main.go:61:4:61:15 | star expression [Category] | main.go:61:3:61:25 | selection of Category | provenance | | | main.go:61:5:61:15 | RequestData [pointer, Category] | main.go:61:4:61:15 | star expression [Category] | provenance | | -| mongoDB.go:40:20:40:30 | call to Referer | mongoDB.go:42:28:42:41 | untrustedInput | provenance | Src:MaD:4 | +| mongoDB.go:40:20:40:30 | call to Referer | mongoDB.go:42:28:42:41 | untrustedInput | provenance | Src:MaD:20 | | mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:50:34:50:39 | filter | provenance | | -| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:61:27:61:32 | filter | provenance | | -| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:63:23:63:28 | filter | provenance | | -| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:64:22:64:27 | filter | provenance | | -| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:66:32:66:37 | filter | provenance | | -| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:69:17:69:22 | filter | provenance | | -| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:70:20:70:25 | filter | provenance | | -| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:71:29:71:34 | filter | provenance | | -| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:72:30:72:35 | filter | provenance | | -| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:73:29:73:34 | filter | provenance | | -| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:78:23:78:28 | filter | provenance | | -| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:79:23:79:28 | filter | provenance | | -| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:80:22:80:27 | filter | provenance | | +| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:61:27:61:32 | filter | provenance | Sink:MaD:4 | +| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:63:23:63:28 | filter | provenance | Sink:MaD:5 | +| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:64:22:64:27 | filter | provenance | Sink:MaD:6 | +| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:66:32:66:37 | filter | provenance | Sink:MaD:7 | +| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:69:17:69:22 | filter | provenance | Sink:MaD:8 | +| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:70:20:70:25 | filter | provenance | Sink:MaD:9 | +| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:71:29:71:34 | filter | provenance | Sink:MaD:10 | +| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:72:30:72:35 | filter | provenance | Sink:MaD:11 | +| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:73:29:73:34 | filter | provenance | Sink:MaD:12 | +| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:78:23:78:28 | filter | provenance | Sink:MaD:13 | +| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:79:23:79:28 | filter | provenance | Sink:MaD:14 | +| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:80:22:80:27 | filter | provenance | Sink:MaD:15 | | mongoDB.go:42:28:42:41 | untrustedInput | mongoDB.go:42:19:42:42 | struct literal | provenance | Config | -| mongoDB.go:50:23:50:40 | struct literal | mongoDB.go:57:22:57:29 | pipeline | provenance | | -| mongoDB.go:50:23:50:40 | struct literal | mongoDB.go:81:18:81:25 | pipeline | provenance | | +| mongoDB.go:50:23:50:40 | struct literal | mongoDB.go:57:22:57:29 | pipeline | provenance | Sink:MaD:3 | +| mongoDB.go:50:23:50:40 | struct literal | mongoDB.go:81:18:81:25 | pipeline | provenance | Sink:MaD:16 | | mongoDB.go:50:34:50:39 | filter | mongoDB.go:50:23:50:40 | struct literal | provenance | Config | models -| 1 | Source: net/http; Request; true; Body; ; ; ; remote; manual | -| 2 | Source: net/http; Request; true; Form; ; ; ; remote; manual | -| 3 | Source: net/http; Request; true; Header; ; ; ; remote; manual | -| 4 | Source: net/http; Request; true; Referer; ; ; ReturnValue; remote; manual | -| 5 | Source: net/http; Request; true; URL; ; ; ; remote; manual | -| 6 | Summary: encoding/json; ; false; Unmarshal; ; ; Argument[0]; Argument[1]; taint; manual | -| 7 | Summary: fmt; ; false; Sprintf; ; ; Argument[1].ArrayElement; ReturnValue; taint; manual | -| 8 | Summary: io/ioutil; ; false; ReadAll; ; ; Argument[0]; ReturnValue[0]; taint; manual | -| 9 | Summary: net/http; Header; true; Get; ; ; Argument[receiver]; ReturnValue; taint; manual | -| 10 | Summary: net/url; URL; true; Query; ; ; Argument[receiver]; ReturnValue; taint; manual | +| 1 | Sink: database/sql; DB; true; Query; ; ; Argument[0]; sql-injection; manual | +| 2 | Sink: database/sql; Tx; true; Query; ; ; Argument[0]; sql-injection; manual | +| 3 | Sink: go.mongodb.org/mongo-driver/mongo; Collection; true; Aggregate; ; ; Argument[1]; nosql-injection; manual | +| 4 | Sink: go.mongodb.org/mongo-driver/mongo; Collection; true; CountDocuments; ; ; Argument[1]; nosql-injection; manual | +| 5 | Sink: go.mongodb.org/mongo-driver/mongo; Collection; true; DeleteMany; ; ; Argument[1]; nosql-injection; manual | +| 6 | Sink: go.mongodb.org/mongo-driver/mongo; Collection; true; DeleteOne; ; ; Argument[1]; nosql-injection; manual | +| 7 | Sink: go.mongodb.org/mongo-driver/mongo; Collection; true; Distinct; ; ; Argument[2]; nosql-injection; manual | +| 8 | Sink: go.mongodb.org/mongo-driver/mongo; Collection; true; Find; ; ; Argument[1]; nosql-injection; manual | +| 9 | Sink: go.mongodb.org/mongo-driver/mongo; Collection; true; FindOne; ; ; Argument[1]; nosql-injection; manual | +| 10 | Sink: go.mongodb.org/mongo-driver/mongo; Collection; true; FindOneAndDelete; ; ; Argument[1]; nosql-injection; manual | +| 11 | Sink: go.mongodb.org/mongo-driver/mongo; Collection; true; FindOneAndReplace; ; ; Argument[1]; nosql-injection; manual | +| 12 | Sink: go.mongodb.org/mongo-driver/mongo; Collection; true; FindOneAndUpdate; ; ; Argument[1]; nosql-injection; manual | +| 13 | Sink: go.mongodb.org/mongo-driver/mongo; Collection; true; ReplaceOne; ; ; Argument[1]; nosql-injection; manual | +| 14 | Sink: go.mongodb.org/mongo-driver/mongo; Collection; true; UpdateMany; ; ; Argument[1]; nosql-injection; manual | +| 15 | Sink: go.mongodb.org/mongo-driver/mongo; Collection; true; UpdateOne; ; ; Argument[1]; nosql-injection; manual | +| 16 | Sink: go.mongodb.org/mongo-driver/mongo; Collection; true; Watch; ; ; Argument[1]; nosql-injection; manual | +| 17 | Source: net/http; Request; true; Body; ; ; ; remote; manual | +| 18 | Source: net/http; Request; true; Form; ; ; ; remote; manual | +| 19 | Source: net/http; Request; true; Header; ; ; ; remote; manual | +| 20 | Source: net/http; Request; true; Referer; ; ; ReturnValue; remote; manual | +| 21 | Source: net/http; Request; true; URL; ; ; ; remote; manual | +| 22 | Summary: encoding/json; ; false; Unmarshal; ; ; Argument[0]; Argument[1]; taint; manual | +| 23 | Summary: fmt; ; false; Sprintf; ; ; Argument[1].ArrayElement; ReturnValue; taint; manual | +| 24 | Summary: io/ioutil; ; false; ReadAll; ; ; Argument[0]; ReturnValue[0]; taint; manual | +| 25 | Summary: net/http; Header; true; Get; ; ; Argument[receiver]; ReturnValue; taint; manual | +| 26 | Summary: net/url; URL; true; Query; ; ; Argument[receiver]; ReturnValue; taint; manual | nodes | SqlInjection.go:10:7:11:30 | []type{args} [array] | semmle.label | []type{args} [array] | | SqlInjection.go:10:7:11:30 | call to Sprintf | semmle.label | call to Sprintf | diff --git a/go/ql/test/query-tests/Security/CWE-117/LogInjection.go b/go/ql/test/query-tests/Security/CWE-117/LogInjection.go index 4f02cc9aef83..6fb628c4cc38 100644 --- a/go/ql/test/query-tests/Security/CWE-117/LogInjection.go +++ b/go/ql/test/query-tests/Security/CWE-117/LogInjection.go @@ -7,7 +7,7 @@ package main //go:generate depstubber -vendor github.com/davecgh/go-spew/spew "" Dump,Errorf,Print,Printf,Println,Fdump,Fprint,Fprintf,Fprintln //go:generate depstubber -vendor github.com/elazarl/goproxy ProxyCtx "" //go:generate depstubber -vendor github.com/golang/glog Level,Verbose Info,InfoDepth,Infof,Infoln,Error,ErrorDepth,Errorf,Errorln,Fatal,FatalDepth,Fatalf,Fatalln,Exit,ExitDepth,Exitf,Exitln,V -//go:generate depstubber -vendor github.com/sirupsen/logrus Fields,Entry,Logger,Level Debug,Debugf,Debugln,Error,Errorf,Errorln,Fatal,Fatalf,Fatalln,Info,Infof,Infoln,Panic,Panicf,Panicln,Print,Printf,Println,Trace,Tracef,Traceln,Warn,Warnf,Warnln,Warning,Warningf,Warningln,WithFields,WithField +//go:generate depstubber -vendor github.com/sirupsen/logrus FieldLogger,Fields,Entry,Logger,Level Debug,Debugf,Debugln,Error,Errorf,Errorln,Fatal,Fatalf,Fatalln,Info,Infof,Infoln,New,NewEntry,Panic,Panicf,Panicln,Print,Printf,Println,Trace,Tracef,Traceln,Warn,Warnf,Warnln,Warning,Warningf,Warningln,WithError,WithFields,WithField //go:generate depstubber -vendor go.uber.org/zap Logger,SugaredLogger NewProduction import ( @@ -30,6 +30,7 @@ import ( func handler(req *http.Request, ctx *goproxy.ProxyCtx) { username := req.URL.Query()["username"][0] + slice := []any{"username", username} testFlag := req.URL.Query()["testFlag"][0] { @@ -170,129 +171,180 @@ func handler(req *http.Request, ctx *goproxy.ProxyCtx) { } // sirupsen/logrus { - logrus.Debug(username) // $ hasTaintFlow="username" - logrus.Debugf(username, "") // $ hasTaintFlow="username" - logrus.Debugf("", username) // $ hasTaintFlow="username" - logrus.Debugln(username) // $ hasTaintFlow="username" - logrus.Error(username) // $ hasTaintFlow="username" - logrus.Errorf(username, "") // $ hasTaintFlow="username" - logrus.Errorf("", username) // $ hasTaintFlow="username" - logrus.Errorln(username) // $ hasTaintFlow="username" - logrus.Fatal(username) // $ hasTaintFlow="username" - logrus.Fatalf(username, "") // $ hasTaintFlow="username" - logrus.Fatalf("", username) // $ hasTaintFlow="username" - logrus.Fatalln(username) // $ hasTaintFlow="username" - logrus.Info(username) // $ hasTaintFlow="username" - logrus.Infof(username, "") // $ hasTaintFlow="username" - logrus.Infof("", username) // $ hasTaintFlow="username" - logrus.Infoln(username) // $ hasTaintFlow="username" - logrus.Panic(username) // $ hasTaintFlow="username" - logrus.Panicf(username, "") // $ hasTaintFlow="username" - logrus.Panicf("", username) // $ hasTaintFlow="username" - logrus.Panicln(username) // $ hasTaintFlow="username" - logrus.Print(username) // $ hasTaintFlow="username" - logrus.Printf(username, "") // $ hasTaintFlow="username" - logrus.Printf("", username) // $ hasTaintFlow="username" - logrus.Println(username) // $ hasTaintFlow="username" - logrus.Trace(username) // $ hasTaintFlow="username" - logrus.Tracef(username, "") // $ hasTaintFlow="username" - logrus.Tracef("", username) // $ hasTaintFlow="username" - logrus.Traceln(username) // $ hasTaintFlow="username" - logrus.Warn(username) // $ hasTaintFlow="username" - logrus.Warnf(username, "") // $ hasTaintFlow="username" - logrus.Warnf("", username) // $ hasTaintFlow="username" - logrus.Warnln(username) // $ hasTaintFlow="username" - logrus.Warning(username) // $ hasTaintFlow="username" - logrus.Warningf(username, "") // $ hasTaintFlow="username" - logrus.Warningf("", username) // $ hasTaintFlow="username" - logrus.Warningln(username) // $ hasTaintFlow="username" - + err := fmt.Errorf("error: %s", username) fields := make(logrus.Fields) fields["username"] = username - entry := logrus.WithFields(fields) // $ hasTaintFlow="fields" - entry = logrus.WithField("username", username) // $ hasTaintFlow="username" - entry.Debug(username) // $ hasTaintFlow="username" - entry.Debugf(username, "") // $ hasTaintFlow="username" - entry.Debugf("", username) // $ hasTaintFlow="username" - entry.Debugln(username) // $ hasTaintFlow="username" - entry.Error(username) // $ hasTaintFlow="username" - entry.Errorf(username, "") // $ hasTaintFlow="username" - entry.Errorf("", username) // $ hasTaintFlow="username" - entry.Errorln(username) // $ hasTaintFlow="username" - entry.Fatal(username) // $ hasTaintFlow="username" - entry.Fatalf(username, "") // $ hasTaintFlow="username" - entry.Fatalf("", username) // $ hasTaintFlow="username" - entry.Fatalln(username) // $ hasTaintFlow="username" - entry.Info(username) // $ hasTaintFlow="username" - entry.Infof(username, "") // $ hasTaintFlow="username" - entry.Infof("", username) // $ hasTaintFlow="username" - entry.Infoln(username) // $ hasTaintFlow="username" - entry.Log(0, username) // $ hasTaintFlow="username" - entry.Logf(0, username, "") // $ hasTaintFlow="username" - entry.Logf(0, "", username) // $ hasTaintFlow="username" - entry.Logln(0, username) // $ hasTaintFlow="username" - entry.Panic(username) // $ hasTaintFlow="username" - entry.Panicf(username, "") // $ hasTaintFlow="username" - entry.Panicf("", username) // $ hasTaintFlow="username" - entry.Panicln(username) // $ hasTaintFlow="username" - entry.Print(username) // $ hasTaintFlow="username" - entry.Printf(username, "") // $ hasTaintFlow="username" - entry.Printf("", username) // $ hasTaintFlow="username" - entry.Println(username) // $ hasTaintFlow="username" - entry.Trace(username) // $ hasTaintFlow="username" - entry.Tracef(username, "") // $ hasTaintFlow="username" - entry.Tracef("", username) // $ hasTaintFlow="username" - entry.Traceln(username) // $ hasTaintFlow="username" - entry.Warn(username) // $ hasTaintFlow="username" - entry.Warnf(username, "") // $ hasTaintFlow="username" - entry.Warnf("", username) // $ hasTaintFlow="username" - entry.Warnln(username) // $ hasTaintFlow="username" - entry.Warning(username) // $ hasTaintFlow="username" - entry.Warningf(username, "") // $ hasTaintFlow="username" - entry.Warningf("", username) // $ hasTaintFlow="username" - entry.Warningln(username) // $ hasTaintFlow="username" - - logger := entry.Logger - logger.Debug(username) // $ hasTaintFlow="username" - logger.Debugf(username, "") // $ hasTaintFlow="username" - logger.Debugf("", username) // $ hasTaintFlow="username" - logger.Debugln(username) // $ hasTaintFlow="username" - logger.Error(username) // $ hasTaintFlow="username" - logger.Errorf(username, "") // $ hasTaintFlow="username" - logger.Errorf("", username) // $ hasTaintFlow="username" - logger.Errorln(username) // $ hasTaintFlow="username" - logger.Fatal(username) // $ hasTaintFlow="username" - logger.Fatalf(username, "") // $ hasTaintFlow="username" - logger.Fatalf("", username) // $ hasTaintFlow="username" - logger.Fatalln(username) // $ hasTaintFlow="username" - logger.Info(username) // $ hasTaintFlow="username" - logger.Infof(username, "") // $ hasTaintFlow="username" - logger.Infof("", username) // $ hasTaintFlow="username" - logger.Infoln(username) // $ hasTaintFlow="username" - logger.Log(0, username) // $ hasTaintFlow="username" - logger.Logf(0, username, "") // $ hasTaintFlow="username" - logger.Logf(0, "", username) // $ hasTaintFlow="username" - logger.Logln(0, username) // $ hasTaintFlow="username" - logger.Panic(username) // $ hasTaintFlow="username" - logger.Panicf(username, "") // $ hasTaintFlow="username" - logger.Panicf("", username) // $ hasTaintFlow="username" - logger.Panicln(username) // $ hasTaintFlow="username" - logger.Print(username) // $ hasTaintFlow="username" - logger.Printf(username, "") // $ hasTaintFlow="username" - logger.Printf("", username) // $ hasTaintFlow="username" - logger.Println(username) // $ hasTaintFlow="username" - logger.Trace(username) // $ hasTaintFlow="username" - logger.Tracef(username, "") // $ hasTaintFlow="username" - logger.Tracef("", username) // $ hasTaintFlow="username" - logger.Traceln(username) // $ hasTaintFlow="username" - logger.Warn(username) // $ hasTaintFlow="username" - logger.Warnf(username, "") // $ hasTaintFlow="username" - logger.Warnf("", username) // $ hasTaintFlow="username" - logger.Warnln(username) // $ hasTaintFlow="username" - logger.Warning(username) // $ hasTaintFlow="username" - logger.Warningf(username, "") // $ hasTaintFlow="username" - logger.Warningf("", username) // $ hasTaintFlow="username" - logger.Warningln(username) // $ hasTaintFlow="username" + logger := logrus.New() + entry := logrus.NewEntry(logger) + + logrus.Debug(username) // $ hasTaintFlow="username" + logrus.Debugf(username, "") // $ hasTaintFlow="username" + logrus.Debugf("", username) // $ hasTaintFlow="username" + logrus.Debugln(username) // $ hasTaintFlow="username" + logrus.Error(username) // $ hasTaintFlow="username" + logrus.Errorf(username, "") // $ hasTaintFlow="username" + logrus.Errorf("", username) // $ hasTaintFlow="username" + logrus.Errorln(username) // $ hasTaintFlow="username" + logrus.Fatal(username) // $ hasTaintFlow="username" + logrus.Fatalf(username, "") // $ hasTaintFlow="username" + logrus.Fatalf("", username) // $ hasTaintFlow="username" + logrus.Fatalln(username) // $ hasTaintFlow="username" + logrus.Info(username) // $ hasTaintFlow="username" + logrus.Infof(username, "") // $ hasTaintFlow="username" + logrus.Infof("", username) // $ hasTaintFlow="username" + logrus.Infoln(username) // $ hasTaintFlow="username" + logrus.Panic(username) // $ hasTaintFlow="username" + logrus.Panicf(username, "") // $ hasTaintFlow="username" + logrus.Panicf("", username) // $ hasTaintFlow="username" + logrus.Panicln(username) // $ hasTaintFlow="username" + logrus.Print(username) // $ hasTaintFlow="username" + logrus.Printf(username, "") // $ hasTaintFlow="username" + logrus.Printf("", username) // $ hasTaintFlow="username" + logrus.Println(username) // $ hasTaintFlow="username" + logrus.Trace(username) // $ hasTaintFlow="username" + logrus.Tracef(username, "") // $ hasTaintFlow="username" + logrus.Tracef("", username) // $ hasTaintFlow="username" + logrus.Traceln(username) // $ hasTaintFlow="username" + logrus.Warn(username) // $ hasTaintFlow="username" + logrus.Warnf(username, "") // $ hasTaintFlow="username" + logrus.Warnf("", username) // $ hasTaintFlow="username" + logrus.Warnln(username) // $ hasTaintFlow="username" + logrus.Warning(username) // $ hasTaintFlow="username" + logrus.Warningf(username, "") // $ hasTaintFlow="username" + logrus.Warningf("", username) // $ hasTaintFlow="username" + logrus.Warningln(username) // $ hasTaintFlow="username" + logrus.WithError(err) // $ hasTaintFlow="err" + logrus.WithField(username, "") // $ hasTaintFlow="username" + logrus.WithField("", username) // $ hasTaintFlow="username" + logrus.WithFields(fields) // $ hasTaintFlow="fields" + + entry.Debug(username) // $ hasTaintFlow="username" + entry.Debugf(username, "") // $ hasTaintFlow="username" + entry.Debugf("", username) // $ hasTaintFlow="username" + entry.Debugln(username) // $ hasTaintFlow="username" + entry.Error(username) // $ hasTaintFlow="username" + entry.Errorf(username, "") // $ hasTaintFlow="username" + entry.Errorf("", username) // $ hasTaintFlow="username" + entry.Errorln(username) // $ hasTaintFlow="username" + entry.Fatal(username) // $ hasTaintFlow="username" + entry.Fatalf(username, "") // $ hasTaintFlow="username" + entry.Fatalf("", username) // $ hasTaintFlow="username" + entry.Fatalln(username) // $ hasTaintFlow="username" + entry.Info(username) // $ hasTaintFlow="username" + entry.Infof(username, "") // $ hasTaintFlow="username" + entry.Infof("", username) // $ hasTaintFlow="username" + entry.Infoln(username) // $ hasTaintFlow="username" + entry.Log(0, username) // $ hasTaintFlow="username" + entry.Logf(0, username, "") // $ hasTaintFlow="username" + entry.Logf(0, "", username) // $ hasTaintFlow="username" + entry.Logln(0, username) // $ hasTaintFlow="username" + entry.Panic(username) // $ hasTaintFlow="username" + entry.Panicf(username, "") // $ hasTaintFlow="username" + entry.Panicf("", username) // $ hasTaintFlow="username" + entry.Panicln(username) // $ hasTaintFlow="username" + entry.Print(username) // $ hasTaintFlow="username" + entry.Printf(username, "") // $ hasTaintFlow="username" + entry.Printf("", username) // $ hasTaintFlow="username" + entry.Println(username) // $ hasTaintFlow="username" + entry.Trace(username) // $ hasTaintFlow="username" + entry.Tracef(username, "") // $ hasTaintFlow="username" + entry.Tracef("", username) // $ hasTaintFlow="username" + entry.Traceln(username) // $ hasTaintFlow="username" + entry.Warn(username) // $ hasTaintFlow="username" + entry.Warnf(username, "") // $ hasTaintFlow="username" + entry.Warnf("", username) // $ hasTaintFlow="username" + entry.Warnln(username) // $ hasTaintFlow="username" + entry.Warning(username) // $ hasTaintFlow="username" + entry.Warningf(username, "") // $ hasTaintFlow="username" + entry.Warningf("", username) // $ hasTaintFlow="username" + entry.Warningln(username) // $ hasTaintFlow="username" + entry.WithError(err) // $ hasTaintFlow="err" + entry.WithField(username, "") // $ hasTaintFlow="username" + entry.WithField("", username) // $ hasTaintFlow="username" + entry.WithFields(fields) // $ hasTaintFlow="fields" + + logger.Debug(username) // $ hasTaintFlow="username" + logger.Debugf(username, "") // $ hasTaintFlow="username" + logger.Debugf("", username) // $ hasTaintFlow="username" + logger.Debugln(username) // $ hasTaintFlow="username" + logger.Error(username) // $ hasTaintFlow="username" + logger.Errorf(username, "") // $ hasTaintFlow="username" + logger.Errorf("", username) // $ hasTaintFlow="username" + logger.Errorln(username) // $ hasTaintFlow="username" + logger.Fatal(username) // $ hasTaintFlow="username" + logger.Fatalf(username, "") // $ hasTaintFlow="username" + logger.Fatalf("", username) // $ hasTaintFlow="username" + logger.Fatalln(username) // $ hasTaintFlow="username" + logger.Info(username) // $ hasTaintFlow="username" + logger.Infof(username, "") // $ hasTaintFlow="username" + logger.Infof("", username) // $ hasTaintFlow="username" + logger.Infoln(username) // $ hasTaintFlow="username" + logger.Log(0, username) // $ hasTaintFlow="username" + logger.Logf(0, username, "") // $ hasTaintFlow="username" + logger.Logf(0, "", username) // $ hasTaintFlow="username" + logger.Logln(0, username) // $ hasTaintFlow="username" + logger.Panic(username) // $ hasTaintFlow="username" + logger.Panicf(username, "") // $ hasTaintFlow="username" + logger.Panicf("", username) // $ hasTaintFlow="username" + logger.Panicln(username) // $ hasTaintFlow="username" + logger.Print(username) // $ hasTaintFlow="username" + logger.Printf(username, "") // $ hasTaintFlow="username" + logger.Printf("", username) // $ hasTaintFlow="username" + logger.Println(username) // $ hasTaintFlow="username" + logger.Trace(username) // $ hasTaintFlow="username" + logger.Tracef(username, "") // $ hasTaintFlow="username" + logger.Tracef("", username) // $ hasTaintFlow="username" + logger.Traceln(username) // $ hasTaintFlow="username" + logger.Warn(username) // $ hasTaintFlow="username" + logger.Warnf(username, "") // $ hasTaintFlow="username" + logger.Warnf("", username) // $ hasTaintFlow="username" + logger.Warnln(username) // $ hasTaintFlow="username" + logger.Warning(username) // $ hasTaintFlow="username" + logger.Warningf(username, "") // $ hasTaintFlow="username" + logger.Warningf("", username) // $ hasTaintFlow="username" + logger.Warningln(username) // $ hasTaintFlow="username" + logger.WithError(err) // $ hasTaintFlow="err" + logger.WithField(username, "") // $ hasTaintFlow="username" + logger.WithField("", username) // $ hasTaintFlow="username" + logger.WithFields(fields) // $ hasTaintFlow="fields" + + var fieldlogger logrus.FieldLogger = entry + fieldlogger.Debug(username) // $ hasTaintFlow="username" + fieldlogger.Debugf(username, "") // $ hasTaintFlow="username" + fieldlogger.Debugf("", username) // $ hasTaintFlow="username" + fieldlogger.Debugln(username) // $ hasTaintFlow="username" + fieldlogger.Error(username) // $ hasTaintFlow="username" + fieldlogger.Errorf(username, "") // $ hasTaintFlow="username" + fieldlogger.Errorf("", username) // $ hasTaintFlow="username" + fieldlogger.Errorln(username) // $ hasTaintFlow="username" + fieldlogger.Fatal(username) // $ hasTaintFlow="username" + fieldlogger.Fatalf(username, "") // $ hasTaintFlow="username" + fieldlogger.Fatalf("", username) // $ hasTaintFlow="username" + fieldlogger.Fatalln(username) // $ hasTaintFlow="username" + fieldlogger.Info(username) // $ hasTaintFlow="username" + fieldlogger.Infof(username, "") // $ hasTaintFlow="username" + fieldlogger.Infof("", username) // $ hasTaintFlow="username" + fieldlogger.Infoln(username) // $ hasTaintFlow="username" + fieldlogger.Panic(username) // $ hasTaintFlow="username" + fieldlogger.Panicf(username, "") // $ hasTaintFlow="username" + fieldlogger.Panicf("", username) // $ hasTaintFlow="username" + fieldlogger.Panicln(username) // $ hasTaintFlow="username" + fieldlogger.Print(username) // $ hasTaintFlow="username" + fieldlogger.Printf(username, "") // $ hasTaintFlow="username" + fieldlogger.Printf("", username) // $ hasTaintFlow="username" + fieldlogger.Println(username) // $ hasTaintFlow="username" + fieldlogger.Warn(username) // $ hasTaintFlow="username" + fieldlogger.Warnf(username, "") // $ hasTaintFlow="username" + fieldlogger.Warnf("", username) // $ hasTaintFlow="username" + fieldlogger.Warnln(username) // $ hasTaintFlow="username" + fieldlogger.Warning(username) // $ hasTaintFlow="username" + fieldlogger.Warningf(username, "") // $ hasTaintFlow="username" + fieldlogger.Warningf("", username) // $ hasTaintFlow="username" + fieldlogger.Warningln(username) // $ hasTaintFlow="username" + fieldlogger.WithError(err) // $ hasTaintFlow="err" + fieldlogger.WithField(username, "") // $ hasTaintFlow="username" + fieldlogger.WithField("", username) // $ hasTaintFlow="username" + fieldlogger.WithFields(fields) // $ hasTaintFlow="fields" } // davecgh/go-spew/spew { @@ -361,8 +413,34 @@ func handler(req *http.Request, ctx *goproxy.ProxyCtx) { sLogger.Named(username) // $ hasTaintFlow="username" sLogger.With(username) // $ hasTaintFlow="username" } + // heuristic logger interface + { + logger.Printf(username) // $ hasTaintFlow="username" + logger.Printf("%s", username) // $ hasTaintFlow="username" + simpleLogger.Tracew(username) // $ hasTaintFlow="username" + simpleLogger.Tracew("%s", username) // $ hasTaintFlow="username" + simpleLogger.Debugw("%s %s", slice...) // $ hasTaintFlow="slice" + } + } +type Logger interface { + Printf(string, ...interface{}) +} + +type SimpleLogger interface { + Debugw(msg string, keysAndValues ...any) + Infow(msg string, keysAndValues ...any) + Warnw(msg string, keysAndValues ...any) + Errorw(msg string, keysAndValues ...any) + Tracew(msg string, keysAndValues ...any) +} + +var ( + logger Logger + simpleLogger SimpleLogger +) + // GOOD: The user-provided value is escaped before being written to the log. func handlerGood(req *http.Request) { username := req.URL.Query()["username"][0] @@ -598,5 +676,4 @@ func handlerGood4(req *http.Request, ctx *goproxy.ProxyCtx) { } sLogger.Warnf("user %#q logged in.\n", username) // $ hasTaintFlow="username" } - } diff --git a/go/ql/test/query-tests/Security/CWE-117/go.mod b/go/ql/test/query-tests/Security/CWE-117/go.mod index 57b2077a4ed1..906d90f31b66 100644 --- a/go/ql/test/query-tests/Security/CWE-117/go.mod +++ b/go/ql/test/query-tests/Security/CWE-117/go.mod @@ -1,14 +1,33 @@ module main -go 1.14 +go 1.23 require ( github.com/astaxie/beego v1.12.3 + github.com/davecgh/go-spew v1.1.1 github.com/elazarl/goproxy v0.0.0-20211114080932-d06c3be7c11b github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b - github.com/kr/text v0.2.0 // indirect github.com/sirupsen/logrus v1.8.1 - github.com/stretchr/testify v1.6.0 // indirect - golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f // indirect + go.uber.org/zap v1.27.0 k8s.io/klog v1.0.0 ) + +require ( + github.com/beorn7/perks v1.0.1 // indirect + github.com/cespare/xxhash/v2 v2.1.1 // indirect + github.com/golang/protobuf v1.4.2 // indirect + github.com/hashicorp/golang-lru v0.5.4 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect + github.com/prometheus/client_golang v1.7.0 // indirect + github.com/prometheus/client_model v0.2.0 // indirect + github.com/prometheus/common v0.10.0 // indirect + github.com/prometheus/procfs v0.1.3 // indirect + github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644 // indirect + go.uber.org/multierr v1.10.0 // indirect + golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 // indirect + golang.org/x/net v0.0.0-20190620200207-3b0461eec859 // indirect + golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f // indirect + golang.org/x/text v0.3.0 // indirect + google.golang.org/protobuf v1.23.0 // indirect + gopkg.in/yaml.v2 v2.2.8 // indirect +) diff --git a/go/ql/test/query-tests/Security/CWE-117/vendor/github.com/sirupsen/logrus/stub.go b/go/ql/test/query-tests/Security/CWE-117/vendor/github.com/sirupsen/logrus/stub.go index e8f7bccc4465..497d85559bb2 100644 --- a/go/ql/test/query-tests/Security/CWE-117/vendor/github.com/sirupsen/logrus/stub.go +++ b/go/ql/test/query-tests/Security/CWE-117/vendor/github.com/sirupsen/logrus/stub.go @@ -2,7 +2,7 @@ // This is a simple stub for github.com/sirupsen/logrus, strictly for use in testing. // See the LICENSE file for information about the licensing of the original library. -// Source: github.com/sirupsen/logrus (exports: Fields,Entry,Logger,Level; functions: Debug,Debugf,Debugln,Error,Errorf,Errorln,Fatal,Fatalf,Fatalln,Info,Infof,Infoln,Panic,Panicf,Panicln,Print,Printf,Println,Trace,Tracef,Traceln,Warn,Warnf,Warnln,Warning,Warningf,Warningln,WithFields,WithField) +// Source: github.com/sirupsen/logrus (exports: FieldLogger,Fields,Entry,Logger,Level; functions: Debug,Debugf,Debugln,Error,Errorf,Errorln,Fatal,Fatalf,Fatalln,Info,Infof,Infoln,New,NewEntry,Panic,Panicf,Panicln,Print,Printf,Println,Trace,Tracef,Traceln,Warn,Warnf,Warnln,Warning,Warningf,Warningln,WithError,WithFields,WithField) // Package logrus is a stub of github.com/sirupsen/logrus, generated by depstubber. package logrus @@ -148,6 +148,36 @@ func Fatalf(_ string, _ ...interface{}) {} func Fatalln(_ ...interface{}) {} +type FieldLogger interface { + Debug(_ ...interface{}) + Debugf(_ string, _ ...interface{}) + Debugln(_ ...interface{}) + Error(_ ...interface{}) + Errorf(_ string, _ ...interface{}) + Errorln(_ ...interface{}) + Fatal(_ ...interface{}) + Fatalf(_ string, _ ...interface{}) + Fatalln(_ ...interface{}) + Info(_ ...interface{}) + Infof(_ string, _ ...interface{}) + Infoln(_ ...interface{}) + Panic(_ ...interface{}) + Panicf(_ string, _ ...interface{}) + Panicln(_ ...interface{}) + Print(_ ...interface{}) + Printf(_ string, _ ...interface{}) + Println(_ ...interface{}) + Warn(_ ...interface{}) + Warnf(_ string, _ ...interface{}) + Warning(_ ...interface{}) + Warningf(_ string, _ ...interface{}) + Warningln(_ ...interface{}) + Warnln(_ ...interface{}) + WithError(_ error) *Entry + WithField(_ string, _ interface{}) *Entry + WithFields(_ Fields) *Entry +} + type Fields map[string]interface{} type Formatter interface { @@ -332,6 +362,14 @@ func (_ *Logger) WriterLevel(_ Level) *io.PipeWriter { return nil } +func New() *Logger { + return nil +} + +func NewEntry(_ *Logger) *Entry { + return nil +} + func Panic(_ ...interface{}) {} func Panicf(_ string, _ ...interface{}) {} @@ -362,6 +400,10 @@ func Warningln(_ ...interface{}) {} func Warnln(_ ...interface{}) {} +func WithError(_ error) *Entry { + return nil +} + func WithField(_ string, _ interface{}) *Entry { return nil } diff --git a/go/ql/test/query-tests/Security/CWE-117/vendor/modules.txt b/go/ql/test/query-tests/Security/CWE-117/vendor/modules.txt index a6227c09a936..fa7cb0a9a823 100644 --- a/go/ql/test/query-tests/Security/CWE-117/vendor/modules.txt +++ b/go/ql/test/query-tests/Security/CWE-117/vendor/modules.txt @@ -1,24 +1,134 @@ # github.com/astaxie/beego v1.12.3 -## explicit +## explicit; go 1.13 github.com/astaxie/beego +github.com/astaxie/beego/config +github.com/astaxie/beego/context +github.com/astaxie/beego/context/param +github.com/astaxie/beego/grace +github.com/astaxie/beego/logs +github.com/astaxie/beego/session +github.com/astaxie/beego/toolbox +github.com/astaxie/beego/utils +# github.com/beorn7/perks v1.0.1 +## explicit; go 1.11 +github.com/beorn7/perks/quantile +# github.com/cespare/xxhash/v2 v2.1.1 +## explicit; go 1.11 +github.com/cespare/xxhash/v2 +# github.com/davecgh/go-spew v1.1.1 +## explicit +github.com/davecgh/go-spew/spew # github.com/elazarl/goproxy v0.0.0-20211114080932-d06c3be7c11b ## explicit github.com/elazarl/goproxy # github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b ## explicit github.com/golang/glog -# github.com/kr/text v0.2.0 +# github.com/golang/protobuf v1.4.2 +## explicit; go 1.9 +github.com/golang/protobuf/proto +github.com/golang/protobuf/ptypes +github.com/golang/protobuf/ptypes/any +github.com/golang/protobuf/ptypes/duration +github.com/golang/protobuf/ptypes/timestamp +# github.com/hashicorp/golang-lru v0.5.4 +## explicit; go 1.12 +github.com/hashicorp/golang-lru +github.com/hashicorp/golang-lru/simplelru +# github.com/matttproud/golang_protobuf_extensions v1.0.1 ## explicit -github.com/kr/text -# github.com/sirupsen/logrus v1.8.1 +github.com/matttproud/golang_protobuf_extensions/pbutil +# github.com/prometheus/client_golang v1.7.0 +## explicit; go 1.11 +github.com/prometheus/client_golang/prometheus +github.com/prometheus/client_golang/prometheus/internal +github.com/prometheus/client_golang/prometheus/promhttp +# github.com/prometheus/client_model v0.2.0 +## explicit; go 1.9 +github.com/prometheus/client_model/go +# github.com/prometheus/common v0.10.0 +## explicit; go 1.11 +github.com/prometheus/common/expfmt +github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg +github.com/prometheus/common/model +# github.com/prometheus/procfs v0.1.3 +## explicit; go 1.12 +github.com/prometheus/procfs +github.com/prometheus/procfs/internal/fs +github.com/prometheus/procfs/internal/util +# github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644 ## explicit +github.com/shiena/ansicolor +# github.com/sirupsen/logrus v1.8.1 +## explicit; go 1.13 github.com/sirupsen/logrus -# github.com/stretchr/testify v1.6.0 +# go.uber.org/multierr v1.10.0 +## explicit; go 1.19 +go.uber.org/multierr +# go.uber.org/zap v1.27.0 +## explicit; go 1.19 +go.uber.org/zap +go.uber.org/zap/buffer +go.uber.org/zap/internal +go.uber.org/zap/internal/bufferpool +go.uber.org/zap/internal/color +go.uber.org/zap/internal/exit +go.uber.org/zap/internal/pool +go.uber.org/zap/internal/stacktrace +go.uber.org/zap/zapcore +# golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 ## explicit -github.com/stretchr/testify +golang.org/x/crypto/acme +golang.org/x/crypto/acme/autocert +# golang.org/x/net v0.0.0-20190620200207-3b0461eec859 +## explicit; go 1.11 +golang.org/x/net/idna # golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f +## explicit; go 1.12 +golang.org/x/sys/internal/unsafeheader +golang.org/x/sys/unix +golang.org/x/sys/windows +# golang.org/x/text v0.3.0 ## explicit -golang.org/x/sys -# k8s.io/klog v1.0.0 +golang.org/x/text/secure/bidirule +golang.org/x/text/transform +golang.org/x/text/unicode/bidi +golang.org/x/text/unicode/norm +# google.golang.org/protobuf v1.23.0 +## explicit; go 1.9 +google.golang.org/protobuf/encoding/prototext +google.golang.org/protobuf/encoding/protowire +google.golang.org/protobuf/internal/descfmt +google.golang.org/protobuf/internal/descopts +google.golang.org/protobuf/internal/detrand +google.golang.org/protobuf/internal/encoding/defval +google.golang.org/protobuf/internal/encoding/messageset +google.golang.org/protobuf/internal/encoding/tag +google.golang.org/protobuf/internal/encoding/text +google.golang.org/protobuf/internal/errors +google.golang.org/protobuf/internal/fieldnum +google.golang.org/protobuf/internal/fieldsort +google.golang.org/protobuf/internal/filedesc +google.golang.org/protobuf/internal/filetype +google.golang.org/protobuf/internal/flags +google.golang.org/protobuf/internal/genname +google.golang.org/protobuf/internal/impl +google.golang.org/protobuf/internal/mapsort +google.golang.org/protobuf/internal/pragma +google.golang.org/protobuf/internal/set +google.golang.org/protobuf/internal/strs +google.golang.org/protobuf/internal/version +google.golang.org/protobuf/proto +google.golang.org/protobuf/reflect/protoreflect +google.golang.org/protobuf/reflect/protoregistry +google.golang.org/protobuf/runtime/protoiface +google.golang.org/protobuf/runtime/protoimpl +google.golang.org/protobuf/types/known/anypb +google.golang.org/protobuf/types/known/durationpb +google.golang.org/protobuf/types/known/timestamppb +# gopkg.in/yaml.v2 v2.2.8 ## explicit +gopkg.in/yaml.v2 +# k8s.io/klog v1.0.0 +## explicit; go 1.12 k8s.io/klog