Add Bun models and tests

This commit is contained in:
Owen Mansel-Chan
2025-04-02 14:06:29 +01:00
parent ddb7da4c13
commit 1687042c3b
4 changed files with 186 additions and 17 deletions

View File

@@ -3,24 +3,19 @@ extensions:
pack: codeql/go-all
extensible: sourceModel
data:
- ["github.com/uptrace/bun", "AddColumnQuery", True, "Model", "", "", "Argument[0]", "database", "manual"]
- ["github.com/uptrace/bun", "CreateIndexQuery", True, "Model", "", "", "Argument[0]", "database", "manual"]
- ["github.com/uptrace/bun", "CreateTableQuery", True, "Model", "", "", "Argument[0]", "database", "manual"]
- ["github.com/uptrace/bun", "DeleteQuery", True, "Model", "", "", "Argument[0]", "database", "manual"]
- ["github.com/uptrace/bun", "DropIndexQuery", True, "Model", "", "", "Argument[0]", "database", "manual"]
- ["github.com/uptrace/bun", "DropTableQuery", True, "Model", "", "", "Argument[0]", "database", "manual"]
- ["github.com/uptrace/bun", "InsertQuery", True, "Model", "", "", "Argument[0]", "database", "manual"]
- ["github.com/uptrace/bun", "MergeQuery", True, "Model", "", "", "Argument[0]", "database", "manual"]
- ["github.com/uptrace/bun", "DB", True, "Query", "", "", "ReturnValue[0]", "database", "manual"]
- ["github.com/uptrace/bun", "DB", True, "QueryRow", "", "", "ReturnValue", "database", "manual"]
- ["github.com/uptrace/bun", "IDB", True, "QueryContext", "", "", "ReturnValue[0]", "database", "manual"]
- ["github.com/uptrace/bun", "IDB", True, "QueryRowContext", "", "", "ReturnValue", "database", "manual"]
# - ["github.com/uptrace/bun", "RawQuery", True, "Exec", "", "", "Argument[0]", "database", "manual"] # Implemented in QL because variadic arguments as sources aren't supported in this format yet
# - ["github.com/uptrace/bun", "RawQuery", True, "Scan", "", "", "Argument[0]", "database", "manual"] # Implemented in QL because variadic arguments as sources aren't supported in this format yet
# - ["github.com/uptrace/bun", "SelectQuery", True, "Exec", "", "", "Argument[0]", "database", "manual"] # Implemented in QL because variadic arguments as sources aren't supported in this format yet
- ["github.com/uptrace/bun", "SelectQuery", True, "Model", "", "", "Argument[0]", "database", "manual"]
- ["github.com/uptrace/bun", "TruncateQuery", True, "Model", "", "", "Argument[0]", "database", "manual"]
- ["github.com/uptrace/bun", "UpdateQuery", True, "Model", "", "", "Argument[0]", "database", "manual"]
- ["github.com/uptrace/bun", "DeleteQuery", True, "Scan", "", "", "Argument[0]", "database", "manual"]
- ["github.com/uptrace/bun", "InsertQuery", True, "Scan", "", "", "Argument[0]", "database", "manual"]
- ["github.com/uptrace/bun", "MergeQuery", True, "Scan", "", "", "Argument[0]", "database", "manual"]
- ["github.com/uptrace/bun", "RawQuery", True, "Scan", "", "", "Argument[0]", "database", "manual"]
- ["github.com/uptrace/bun", "SelectQuery", True, "Scan", "", "", "Argument[0]", "database", "manual"]
- ["github.com/uptrace/bun", "TruncateQuery", True, "Scan", "", "", "Argument[0]", "database", "manual"]
- ["github.com/uptrace/bun", "UpdateQuery", True, "Scan", "", "", "Argument[0]", "database", "manual"]
- ["github.com/uptrace/bun", "SelectQuery", True, "Rows", "", "", "ReturnValue[0]", "database", "manual"]
# - ["github.com/uptrace/bun", "SelectQuery", True, "Scan", "", "", "Argument[1]", "database", "manual"] # Implemented in QL because variadic arguments as sources aren't supported in this format yet
# - ["github.com/uptrace/bun", "SelectQuery", True, "ScanAndCount", "", "", "Argument[1]", "database", "manual"] # Implemented in QL because variadic arguments as sources aren't supported in this format yet
- ["github.com/uptrace/bun", "Tx", True, "Query", "", "", "ReturnValue[0]", "database", "manual"]
- ["github.com/uptrace/bun", "Tx", True, "QueryRow", "", "", "ReturnValue", "database", "manual"]
- addsTo:
pack: codeql/go-all
extensible: sinkModel
@@ -88,3 +83,9 @@ extensions:
- ["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"]
# - addsTo:
# pack: codeql/go-all
# extensible: summaryModel
# data:
# - ["github.com/uptrace/bun", "DB", True, "ScanRow", "", "", "Argument[1]", "Argument[2].ArrayElement", "taint", "manual"] # Implemented in QL because variadic arguments as outputs aren't supported in this format yet
# - ["github.com/uptrace/bun", "DB", True, "ScanRows", "", "", "Argument[1]", "Argument[2].ArrayElement", "taint", "manual"] # Implemented in QL because variadic arguments as outputs aren't supported in this format yet

View File

@@ -32,6 +32,7 @@ import semmle.go.frameworks.Afero
import semmle.go.frameworks.AwsLambda
import semmle.go.frameworks.Beego
import semmle.go.frameworks.BeegoOrm
import semmle.go.frameworks.Bun
import semmle.go.frameworks.RsCors
import semmle.go.frameworks.Couchbase
import semmle.go.frameworks.Echo

View File

@@ -0,0 +1,90 @@
/**
* Provides classes modeling security-relevant aspects of the `Bun` package.
*/
import go
/**
* Provides classes modeling security-relevant aspects of the `Bun` package.
*/
private module Bun {
private string packagePath() { result = package("github.com/uptrace/bun", "") }
private class RawQuerySources extends SourceNode {
RawQuerySources() {
// func (q *RawQuery) Exec(ctx context.Context, dest ...interface{}) (sql.Result, error)
// func (q *RawQuery) Scan(ctx context.Context, dest ...interface{}) error
exists(DataFlow::CallNode cn, int i |
cn.getTarget().(Method).hasQualifiedName(packagePath(), "RawQuery", ["Exec", "Scan"]) and
i >= 1
|
this = cn.getSyntacticArgument(i)
)
}
override string getThreatModel() { result = "database" }
}
private class SelectQuerySources extends SourceNode {
SelectQuerySources() {
// func (q *SelectQuery) Exec(ctx context.Context, dest ...interface{}) (res sql.Result, err error)
// func (q *SelectQuery) Scan(ctx context.Context, dest ...interface{}) error
// func (q *SelectQuery) ScanAndCount(ctx context.Context, dest ...interface{}) (int, error)
exists(DataFlow::CallNode cn, int i |
cn.getTarget()
.(Method)
.hasQualifiedName(packagePath(), "SelectQuery", ["Exec", "Scan", "ScanAndCount"]) and
i >= 1
|
this = cn.getSyntacticArgument(i)
)
}
override string getThreatModel() { result = "database" }
}
private class DBScanRows extends TaintTracking::FunctionModel, Method {
FunctionInput inp;
FunctionOutput outp;
DBScanRows() {
// func (db *DB) ScanRow(ctx context.Context, rows *sql.Rows, dest ...interface{}) error
// func (db *DB) ScanRows(ctx context.Context, rows *sql.Rows, dest ...interface{}) error
this.hasQualifiedName(packagePath(), "DB", ["ScanRow", "ScanRows"]) and
inp.isParameter(1) and
outp.isParameter(any(int i | i >= 2))
}
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input = inp and output = outp
}
}
// private class BuilderScan extends TaintTracking::FunctionModel, Method {
// FunctionInput inp;
// FunctionOutput outp;
// BuilderScan() {
// // signature: func (b {Insert,Delete,Select,Update}Builder) Scan(dest ...interface{}) error
// this.hasQualifiedName(packagePath(),
// ["DeleteBuilder", "InsertBuilder", "SelectBuilder", "UpdateBuilder"], "Scan") and
// inp.isReceiver() and
// outp.isParameter(_)
// }
// override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// input = inp and output = outp
// }
// }
// private class BuilderScanContext extends TaintTracking::FunctionModel, Method {
// FunctionInput inp;
// FunctionOutput outp;
// BuilderScanContext() {
// // signature: func (b {Insert,Delete,Select,Update}Builder) ScanContext(ctx context.Context, dest ...interface{}) error
// this.hasQualifiedName(packagePath(),
// ["DeleteBuilder", "InsertBuilder", "SelectBuilder", "UpdateBuilder"], "ScanContext") and
// inp.isReceiver() and
// exists(int i | i > 0 | outp.isParameter(i))
// }
// override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// input = inp and output = outp
// }
// }
}

View File

@@ -0,0 +1,77 @@
package test
//go:generate depstubber -vendor github.com/uptrace/bun Conn,DB,RawQuery,SelectQuery,Tx
import (
"context"
"github.com/uptrace/bun"
)
func Test_bun_conn(conn bun.Conn) {
ctx := context.Background()
rows1, _ := conn.QueryContext(ctx, "SELECT * FROM users") // $ source
conn.QueryRowContext(ctx, "SELECT * FROM users") // $ source
ignore(rows1)
}
func Test_bun_db(db bun.DB) {
ctx := context.Background()
rows1, _ := db.Query("SELECT * FROM users") // $ source
for rows1.Next() {
var user User
db.ScanRow(ctx, rows1, &user)
sink(user) // $ hasTaintFlow="user"
}
rows2, _ := db.QueryContext(ctx, "SELECT * FROM users") // $ source
var users []User
db.ScanRows(ctx, rows2, &users)
sink(users) // $ hasTaintFlow="users"
db.QueryRow("SELECT * FROM users") // $ source
db.QueryRowContext(ctx, "SELECT * FROM users") // $ source
}
func Test_bun_rawquery(q bun.RawQuery) {
ctx := context.Background()
var u1 []User
q.Exec(ctx, &u1) // $ source
var u2 []User
q.Scan(ctx, &u2) // $ source
}
func Test_bun_selectquery(q bun.SelectQuery) {
ctx := context.Background()
rows, _ := q.Rows(ctx) // $ source
var u1 []User
q.Exec(ctx, &u1) // $ source
var u2 []User
q.Model(&u2).Scan(ctx) // $ source
var u3 map[string]interface{}
q.Scan(ctx, &u3) // $ source
var u4 []User
q.Model(&u4).ScanAndCount(ctx) // $ source
var u5 map[string]interface{}
q.ScanAndCount(ctx, &u5) // $ source
ignore(rows)
}
func Test_bun_tx(tx bun.Tx) {
ctx := context.Background()
rows1, _ := tx.Query("SELECT * FROM users") // $ source
rows2, _ := tx.QueryContext(ctx, "SELECT * FROM users") // $ source
tx.QueryRow("SELECT * FROM users") // $ source
tx.QueryRowContext(ctx, "SELECT * FROM users") // $ source
ignore(rows1, rows2)
}