diff --git a/go/ql/lib/change-notes/2025-01-09-beego-orm-models.md b/go/ql/lib/change-notes/2025-01-09-beego-orm-models.md new file mode 100644 index 000000000000..e68a5315ff1f --- /dev/null +++ b/go/ql/lib/change-notes/2025-01-09-beego-orm-models.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* `database` local source models have been added for the Beego ORM package. 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 index 08c0572b894a..c629191a3668 100644 --- 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 @@ -6,6 +6,23 @@ extensions: - ["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: sourceModel + data: + - ["group:beego-orm", "DB", True, "Query", "", "", "ReturnValue[0]", "database", "manual"] + - ["group:beego-orm", "DB", True, "QueryContext", "", "", "ReturnValue[0]", "database", "manual"] + - ["group:beego-orm", "DB", True, "QueryRow", "", "", "ReturnValue", "database", "manual"] + - ["group:beego-orm", "DB", True, "QueryRowContext", "", "", "ReturnValue", "database", "manual"] + - ["group:beego-orm", "DQL", True, "Read", "", "", "Argument[0]", "database", "manual"] + - ["group:beego-orm", "DQL", True, "ReadWithCtx", "", "", "Argument[1]", "database", "manual"] + - ["group:beego-orm", "DQL", True, "ReadForUpdate", "", "", "Argument[0]", "database", "manual"] + - ["group:beego-orm", "DQL", True, "ReadForUpdateWithCtx", "", "", "Argument[1]", "database", "manual"] + - ["group:beego-orm", "DQL", True, "ReadOrCreate", "", "", "Argument[0]", "database", "manual"] + - ["group:beego-orm", "DQL", True, "ReadOrCreateWithCtx", "", "", "Argument[1]", "database", "manual"] + - ["group:beego-orm", "Ormer", True, "Read", "", "", "Argument[0]", "database", "manual"] + - ["group:beego-orm", "Ormer", True, "ReadForUpdate", "", "", "Argument[0]", "database", "manual"] + - ["group:beego-orm", "Ormer", True, "ReadOrCreate", "", "", "Argument[0]", "database", "manual"] - addsTo: pack: codeql/go-all extensible: sinkModel @@ -40,3 +57,4 @@ extensions: - ["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/test/library-tests/semmle/go/dataflow/flowsources/local/database/test_beego_orm.go b/go/ql/test/library-tests/semmle/go/dataflow/flowsources/local/database/test_beego_orm.go new file mode 100644 index 000000000000..93138c69a580 --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/flowsources/local/database/test_beego_orm.go @@ -0,0 +1,37 @@ +package test + +import ( + oldOrm "github.com/astaxie/beego/orm" + "github.com/beego/beego/v2/client/orm" +) + +func test_beego_DB(db orm.DB) { + rows, err := db.Query("SELECT * FROM users") // $ source + ignore(rows, err) + + rows, err = db.QueryContext(nil, "SELECT * FROM users") // $ source + ignore(rows, err) + + row := db.QueryRow("SELECT * FROM users") // $ source + ignore(row) + + row = db.QueryRowContext(nil, "SELECT * FROM users") // $ source + ignore(row) +} + +func test_beego_Ormer() { + o := oldOrm.NewOrm() + o.Read(&User{}) // $ source + o.ReadForUpdate(&User{}) // $ source + o.ReadOrCreate(&User{}, "name") // $ source +} + +func test_beego_DQL() { + o := orm.NewOrm() + o.Read(&User{}) // $ source + o.ReadWithCtx(nil, &User{}) // $ source + o.ReadForUpdate(&User{}) // $ source + o.ReadForUpdateWithCtx(nil, &User{}) // $ source + o.ReadOrCreate(&User{}, "name") // $ source + o.ReadOrCreateWithCtx(nil, &User{}, "name") // $ source +} diff --git a/go/ql/test/library-tests/semmle/go/dataflow/flowsources/local/database/vendor/github.com/astaxie/beego/orm/stub.go b/go/ql/test/library-tests/semmle/go/dataflow/flowsources/local/database/vendor/github.com/astaxie/beego/orm/stub.go new file mode 100644 index 000000000000..75e713a364df --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/flowsources/local/database/vendor/github.com/astaxie/beego/orm/stub.go @@ -0,0 +1,150 @@ +// Code generated by depstubber. DO NOT EDIT. +// This is a simple stub for github.com/astaxie/beego/orm, strictly for use in testing. + +// See the LICENSE file for information about the licensing of the original library. +// Source: github.com/astaxie/beego/orm (exports: Ormer; functions: NewOrm) + +// Package orm is a stub of github.com/astaxie/beego/orm, generated by depstubber. +package orm + +import ( + context "context" + sql "database/sql" +) + +type Condition struct{} + +func (_ Condition) And(_ string, _ ...interface{}) *Condition { + return nil +} + +func (_ Condition) AndNot(_ string, _ ...interface{}) *Condition { + return nil +} + +func (_ Condition) Or(_ string, _ ...interface{}) *Condition { + return nil +} + +func (_ Condition) OrNot(_ string, _ ...interface{}) *Condition { + return nil +} + +func (_ Condition) Raw(_ string, _ string) *Condition { + return nil +} + +func (_ *Condition) AndCond(_ *Condition) *Condition { + return nil +} + +func (_ *Condition) AndNotCond(_ *Condition) *Condition { + return nil +} + +func (_ *Condition) IsEmpty() bool { + return false +} + +func (_ *Condition) OrCond(_ *Condition) *Condition { + return nil +} + +func (_ *Condition) OrNotCond(_ *Condition) *Condition { + return nil +} + +type Driver interface { + Name() string + Type() DriverType +} + +type DriverType int + +type Inserter interface { + Close() error + Insert(_ interface{}) (int64, error) +} + +func NewOrm() Ormer { + return nil +} + +type Ormer interface { + Begin() error + BeginTx(_ context.Context, _ *sql.TxOptions) error + Commit() error + DBStats() *sql.DBStats + Delete(_ interface{}, _ ...string) (int64, error) + Driver() Driver + Insert(_ interface{}) (int64, error) + InsertMulti(_ int, _ interface{}) (int64, error) + InsertOrUpdate(_ interface{}, _ ...string) (int64, error) + LoadRelated(_ interface{}, _ string, _ ...interface{}) (int64, error) + QueryM2M(_ interface{}, _ string) QueryM2Mer + QueryTable(_ interface{}) QuerySeter + Raw(_ string, _ ...interface{}) RawSeter + Read(_ interface{}, _ ...string) error + ReadForUpdate(_ interface{}, _ ...string) error + ReadOrCreate(_ interface{}, _ string, _ ...string) (bool, int64, error) + Rollback() error + Update(_ interface{}, _ ...string) (int64, error) + Using(_ string) error +} + +type Params map[string]interface{} + +type ParamsList []interface{} + +type QueryM2Mer interface { + Add(_ ...interface{}) (int64, error) + Clear() (int64, error) + Count() (int64, error) + Exist(_ interface{}) bool + Remove(_ ...interface{}) (int64, error) +} + +type QuerySeter interface { + All(_ interface{}, _ ...string) (int64, error) + Count() (int64, error) + Delete() (int64, error) + Distinct() QuerySeter + Exclude(_ string, _ ...interface{}) QuerySeter + Exist() bool + Filter(_ string, _ ...interface{}) QuerySeter + FilterRaw(_ string, _ string) QuerySeter + ForUpdate() QuerySeter + GetCond() *Condition + GroupBy(_ ...string) QuerySeter + Limit(_ interface{}, _ ...interface{}) QuerySeter + Offset(_ interface{}) QuerySeter + One(_ interface{}, _ ...string) error + OrderBy(_ ...string) QuerySeter + PrepareInsert() (Inserter, error) + RelatedSel(_ ...interface{}) QuerySeter + RowsToMap(_ *Params, _ string, _ string) (int64, error) + RowsToStruct(_ interface{}, _ string, _ string) (int64, error) + SetCond(_ *Condition) QuerySeter + Update(_ Params) (int64, error) + Values(_ *[]Params, _ ...string) (int64, error) + ValuesFlat(_ *ParamsList, _ string) (int64, error) + ValuesList(_ *[]ParamsList, _ ...string) (int64, error) +} + +type RawPreparer interface { + Close() error + Exec(_ ...interface{}) (sql.Result, error) +} + +type RawSeter interface { + Exec() (sql.Result, error) + Prepare() (RawPreparer, error) + QueryRow(_ ...interface{}) error + QueryRows(_ ...interface{}) (int64, error) + RowsToMap(_ *Params, _ string, _ string) (int64, error) + RowsToStruct(_ interface{}, _ string, _ string) (int64, error) + SetArgs(_ ...interface{}) RawSeter + Values(_ *[]Params, _ ...string) (int64, error) + ValuesFlat(_ *ParamsList, _ ...string) (int64, error) + ValuesList(_ *[]ParamsList, _ ...string) (int64, error) +} diff --git a/go/ql/test/library-tests/semmle/go/dataflow/flowsources/local/database/vendor/github.com/beego/beego/v2/client/orm/stub.go b/go/ql/test/library-tests/semmle/go/dataflow/flowsources/local/database/vendor/github.com/beego/beego/v2/client/orm/stub.go new file mode 100644 index 000000000000..4dfcd2aefc85 --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/flowsources/local/database/vendor/github.com/beego/beego/v2/client/orm/stub.go @@ -0,0 +1,300 @@ +// Code generated by depstubber. DO NOT EDIT. +// This is a simple stub for github.com/beego/beego/v2/client/orm, strictly for use in testing. + +// See the LICENSE file for information about the licensing of the original library. +// Source: github.com/beego/beego/v2/client/orm (exports: DQL,DB,Ormer; functions: NewOrm) + +// Package orm is a stub of github.com/beego/beego/v2/client/orm, generated by depstubber. +package orm + +import ( + context "context" + sql "database/sql" + sync "sync" +) + +type Condition struct{} + +func (_ Condition) And(_ string, _ ...interface{}) *Condition { + return nil +} + +func (_ Condition) AndNot(_ string, _ ...interface{}) *Condition { + return nil +} + +func (_ Condition) Or(_ string, _ ...interface{}) *Condition { + return nil +} + +func (_ Condition) OrNot(_ string, _ ...interface{}) *Condition { + return nil +} + +func (_ Condition) Raw(_ string, _ string) *Condition { + return nil +} + +func (_ *Condition) AndCond(_ *Condition) *Condition { + return nil +} + +func (_ *Condition) AndNotCond(_ *Condition) *Condition { + return nil +} + +func (_ *Condition) IsEmpty() bool { + return false +} + +func (_ *Condition) OrCond(_ *Condition) *Condition { + return nil +} + +func (_ *Condition) OrNotCond(_ *Condition) *Condition { + return nil +} + +type DB struct { + RWMutex *sync.RWMutex + DB *sql.DB +} + +func (_ DB) Lock() {} + +func (_ DB) RLock() {} + +func (_ DB) RLocker() sync.Locker { + return nil +} + +func (_ DB) RUnlock() {} + +func (_ DB) TryLock() bool { + return false +} + +func (_ DB) TryRLock() bool { + return false +} + +func (_ DB) Unlock() {} + +func (_ *DB) Begin() (*sql.Tx, error) { + return nil, nil +} + +func (_ *DB) BeginTx(_ context.Context, _ *sql.TxOptions) (*sql.Tx, error) { + return nil, nil +} + +func (_ *DB) Exec(_ string, _ ...interface{}) (sql.Result, error) { + return nil, nil +} + +func (_ *DB) ExecContext(_ context.Context, _ string, _ ...interface{}) (sql.Result, error) { + return nil, nil +} + +func (_ *DB) Prepare(_ string) (*sql.Stmt, error) { + return nil, nil +} + +func (_ *DB) PrepareContext(_ context.Context, _ string) (*sql.Stmt, error) { + return nil, nil +} + +func (_ *DB) Query(_ string, _ ...interface{}) (*sql.Rows, error) { + return nil, nil +} + +func (_ *DB) QueryContext(_ context.Context, _ string, _ ...interface{}) (*sql.Rows, error) { + return nil, nil +} + +func (_ *DB) QueryRow(_ string, _ ...interface{}) *sql.Row { + return nil +} + +func (_ *DB) QueryRowContext(_ context.Context, _ string, _ ...interface{}) *sql.Row { + return nil +} + +type DQL interface { + DBStats() *sql.DBStats + LoadRelated(_ interface{}, _ string, _ ...interface{}) (int64, error) + LoadRelatedWithCtx(_ context.Context, _ interface{}, _ string, _ ...interface{}) (int64, error) + QueryM2M(_ interface{}, _ string) QueryM2Mer + QueryM2MWithCtx(_ context.Context, _ interface{}, _ string) QueryM2Mer + QueryTable(_ interface{}) QuerySeter + QueryTableWithCtx(_ context.Context, _ interface{}) QuerySeter + Read(_ interface{}, _ ...string) error + ReadForUpdate(_ interface{}, _ ...string) error + ReadForUpdateWithCtx(_ context.Context, _ interface{}, _ ...string) error + ReadOrCreate(_ interface{}, _ string, _ ...string) (bool, int64, error) + ReadOrCreateWithCtx(_ context.Context, _ interface{}, _ string, _ ...string) (bool, int64, error) + ReadWithCtx(_ context.Context, _ interface{}, _ ...string) error +} + +type Driver interface { + Name() string + Type() DriverType +} + +type DriverType int + +type Inserter interface { + Close() error + Insert(_ interface{}) (int64, error) + InsertWithCtx(_ context.Context, _ interface{}) (int64, error) +} + +func NewOrm() Ormer { + return nil +} + +type Ormer interface { + Begin() (TxOrmer, error) + BeginWithCtx(_ context.Context) (TxOrmer, error) + BeginWithCtxAndOpts(_ context.Context, _ *sql.TxOptions) (TxOrmer, error) + BeginWithOpts(_ *sql.TxOptions) (TxOrmer, error) + DBStats() *sql.DBStats + Delete(_ interface{}, _ ...string) (int64, error) + DeleteWithCtx(_ context.Context, _ interface{}, _ ...string) (int64, error) + DoTx(_ func(context.Context, TxOrmer) error) error + DoTxWithCtx(_ context.Context, _ func(context.Context, TxOrmer) error) error + DoTxWithCtxAndOpts(_ context.Context, _ *sql.TxOptions, _ func(context.Context, TxOrmer) error) error + DoTxWithOpts(_ *sql.TxOptions, _ func(context.Context, TxOrmer) error) error + Driver() Driver + Insert(_ interface{}) (int64, error) + InsertMulti(_ int, _ interface{}) (int64, error) + InsertMultiWithCtx(_ context.Context, _ int, _ interface{}) (int64, error) + InsertOrUpdate(_ interface{}, _ ...string) (int64, error) + InsertOrUpdateWithCtx(_ context.Context, _ interface{}, _ ...string) (int64, error) + InsertWithCtx(_ context.Context, _ interface{}) (int64, error) + LoadRelated(_ interface{}, _ string, _ ...interface{}) (int64, error) + LoadRelatedWithCtx(_ context.Context, _ interface{}, _ string, _ ...interface{}) (int64, error) + QueryM2M(_ interface{}, _ string) QueryM2Mer + QueryM2MWithCtx(_ context.Context, _ interface{}, _ string) QueryM2Mer + QueryTable(_ interface{}) QuerySeter + QueryTableWithCtx(_ context.Context, _ interface{}) QuerySeter + Raw(_ string, _ ...interface{}) RawSeter + RawWithCtx(_ context.Context, _ string, _ ...interface{}) RawSeter + Read(_ interface{}, _ ...string) error + ReadForUpdate(_ interface{}, _ ...string) error + ReadForUpdateWithCtx(_ context.Context, _ interface{}, _ ...string) error + ReadOrCreate(_ interface{}, _ string, _ ...string) (bool, int64, error) + ReadOrCreateWithCtx(_ context.Context, _ interface{}, _ string, _ ...string) (bool, int64, error) + ReadWithCtx(_ context.Context, _ interface{}, _ ...string) error + Update(_ interface{}, _ ...string) (int64, error) + UpdateWithCtx(_ context.Context, _ interface{}, _ ...string) (int64, error) +} + +type Params map[string]interface{} + +type ParamsList []interface{} + +type QueryM2Mer interface { + Add(_ ...interface{}) (int64, error) + AddWithCtx(_ context.Context, _ ...interface{}) (int64, error) + Clear() (int64, error) + ClearWithCtx(_ context.Context) (int64, error) + Count() (int64, error) + CountWithCtx(_ context.Context) (int64, error) + Exist(_ interface{}) bool + ExistWithCtx(_ context.Context, _ interface{}) bool + Remove(_ ...interface{}) (int64, error) + RemoveWithCtx(_ context.Context, _ ...interface{}) (int64, error) +} + +type QuerySeter interface { + Aggregate(_ string) QuerySeter + All(_ interface{}, _ ...string) (int64, error) + AllWithCtx(_ context.Context, _ interface{}, _ ...string) (int64, error) + Count() (int64, error) + CountWithCtx(_ context.Context) (int64, error) + Delete() (int64, error) + DeleteWithCtx(_ context.Context) (int64, error) + Distinct() QuerySeter + Exclude(_ string, _ ...interface{}) QuerySeter + Exist() bool + ExistWithCtx(_ context.Context) bool + Filter(_ string, _ ...interface{}) QuerySeter + FilterRaw(_ string, _ string) QuerySeter + ForUpdate() QuerySeter + ForceIndex(_ ...string) QuerySeter + GetCond() *Condition + GroupBy(_ ...string) QuerySeter + IgnoreIndex(_ ...string) QuerySeter + Limit(_ interface{}, _ ...interface{}) QuerySeter + Offset(_ interface{}) QuerySeter + One(_ interface{}, _ ...string) error + OneWithCtx(_ context.Context, _ interface{}, _ ...string) error + OrderBy(_ ...string) QuerySeter + OrderClauses(_ ...interface{}) QuerySeter + PrepareInsert() (Inserter, error) + PrepareInsertWithCtx(_ context.Context) (Inserter, error) + RelatedSel(_ ...interface{}) QuerySeter + RowsToMap(_ *Params, _ string, _ string) (int64, error) + RowsToStruct(_ interface{}, _ string, _ string) (int64, error) + SetCond(_ *Condition) QuerySeter + Update(_ Params) (int64, error) + UpdateWithCtx(_ context.Context, _ Params) (int64, error) + UseIndex(_ ...string) QuerySeter + Values(_ *[]Params, _ ...string) (int64, error) + ValuesFlat(_ *ParamsList, _ string) (int64, error) + ValuesFlatWithCtx(_ context.Context, _ *ParamsList, _ string) (int64, error) + ValuesList(_ *[]ParamsList, _ ...string) (int64, error) + ValuesListWithCtx(_ context.Context, _ *[]ParamsList, _ ...string) (int64, error) + ValuesWithCtx(_ context.Context, _ *[]Params, _ ...string) (int64, error) +} + +type RawPreparer interface { + Close() error + Exec(_ ...interface{}) (sql.Result, error) +} + +type RawSeter interface { + Exec() (sql.Result, error) + Prepare() (RawPreparer, error) + QueryRow(_ ...interface{}) error + QueryRows(_ ...interface{}) (int64, error) + RowsToMap(_ *Params, _ string, _ string) (int64, error) + RowsToStruct(_ interface{}, _ string, _ string) (int64, error) + SetArgs(_ ...interface{}) RawSeter + Values(_ *[]Params, _ ...string) (int64, error) + ValuesFlat(_ *ParamsList, _ ...string) (int64, error) + ValuesList(_ *[]ParamsList, _ ...string) (int64, error) +} + +type TxOrmer interface { + Commit() error + DBStats() *sql.DBStats + Delete(_ interface{}, _ ...string) (int64, error) + DeleteWithCtx(_ context.Context, _ interface{}, _ ...string) (int64, error) + Driver() Driver + Insert(_ interface{}) (int64, error) + InsertMulti(_ int, _ interface{}) (int64, error) + InsertMultiWithCtx(_ context.Context, _ int, _ interface{}) (int64, error) + InsertOrUpdate(_ interface{}, _ ...string) (int64, error) + InsertOrUpdateWithCtx(_ context.Context, _ interface{}, _ ...string) (int64, error) + InsertWithCtx(_ context.Context, _ interface{}) (int64, error) + LoadRelated(_ interface{}, _ string, _ ...interface{}) (int64, error) + LoadRelatedWithCtx(_ context.Context, _ interface{}, _ string, _ ...interface{}) (int64, error) + QueryM2M(_ interface{}, _ string) QueryM2Mer + QueryM2MWithCtx(_ context.Context, _ interface{}, _ string) QueryM2Mer + QueryTable(_ interface{}) QuerySeter + QueryTableWithCtx(_ context.Context, _ interface{}) QuerySeter + Raw(_ string, _ ...interface{}) RawSeter + RawWithCtx(_ context.Context, _ string, _ ...interface{}) RawSeter + Read(_ interface{}, _ ...string) error + ReadForUpdate(_ interface{}, _ ...string) error + ReadForUpdateWithCtx(_ context.Context, _ interface{}, _ ...string) error + ReadOrCreate(_ interface{}, _ string, _ ...string) (bool, int64, error) + ReadOrCreateWithCtx(_ context.Context, _ interface{}, _ string, _ ...string) (bool, int64, error) + ReadWithCtx(_ context.Context, _ interface{}, _ ...string) error + Rollback() error + RollbackUnlessCommit() error + Update(_ interface{}, _ ...string) (int64, error) + UpdateWithCtx(_ context.Context, _ interface{}, _ ...string) (int64, error) +} diff --git a/go/ql/test/library-tests/semmle/go/frameworks/BeegoOrm/StoredXss.expected b/go/ql/test/library-tests/semmle/go/frameworks/BeegoOrm/StoredXss.expected index 861e3e97ed14..530034fac918 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/BeegoOrm/StoredXss.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/BeegoOrm/StoredXss.expected @@ -1,8 +1,8 @@ edges -| test.go:80:13:80:16 | &... | test.go:81:13:81:29 | type conversion | provenance | | -| test.go:80:13:80:16 | &... | test.go:82:13:82:43 | type conversion | provenance | | -| test.go:85:22:85:26 | &... | test.go:86:13:86:30 | type conversion | provenance | | -| test.go:89:21:89:25 | &... | test.go:90:13:90:30 | type conversion | provenance | | +| test.go:80:13:80:16 | &... | test.go:81:13:81:29 | type conversion | provenance | Src:MaD:339 | +| test.go:80:13:80:16 | &... | test.go:82:13:82:43 | type conversion | provenance | Src:MaD:339 | +| test.go:85:22:85:26 | &... | test.go:86:13:86:30 | type conversion | provenance | Src:MaD:340 | +| test.go:89:21:89:25 | &... | test.go:90:13:90:30 | type conversion | provenance | Src:MaD:341 | | test.go:95:20:95:36 | call to Value | test.go:95:13:95:37 | type conversion | provenance | | | test.go:96:20:96:39 | call to RawValue | test.go:96:13:96:49 | type conversion | provenance | | | test.go:97:20:97:37 | call to String | test.go:97:13:97:38 | type conversion | provenance | |