Merge branch 'main' into redsun82/rust-str

This commit is contained in:
Paolo Tranquilli
2024-11-22 14:44:48 +01:00
127 changed files with 1500 additions and 3253 deletions

View File

@@ -33,9 +33,9 @@ jobs:
# run with --check-only if running in a PR (github.sha != main)
if : ${{ github.event_name == 'pull_request' }}
shell: bash
run: codeql query compile -q -j0 */ql/{src,examples} --keep-going --warnings=error --check-only --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}" --compilation-cache-size=500
run: codeql query compile -q -j0 */ql/{src,examples} --keep-going --warnings=error --check-only --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}" --compilation-cache-size=500 --ram=56000
- name: compile queries - full
# do full compile if running on main - this populates the cache
if : ${{ github.event_name != 'pull_request' }}
shell: bash
run: codeql query compile -q -j0 */ql/{src,examples} --keep-going --warnings=error --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}" --compilation-cache-size=500
run: codeql query compile -q -j0 */ql/{src,examples} --keep-going --warnings=error --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}" --compilation-cache-size=500 --ram=56000

View File

@@ -1,121 +1,141 @@
package,sink,source,summary,sink:command-injection,sink:credentials-key,sink:jwt,sink:path-injection,sink:regex-use[0],sink:regex-use[1],sink:regex-use[c],sink:request-forgery,sink:request-forgery[TCP Addr + Port],sink:url-redirection,sink:url-redirection[0],sink:url-redirection[receiver],sink:xpath-injection,source:environment,source:file,source:remote,source:stdin,summary:taint,summary:value
,,,8,,,,,,,,,,,,,,,,,,3,5
archive/tar,,,5,,,,,,,,,,,,,,,,,,5,
archive/zip,,,6,,,,,,,,,,,,,,,,,,6,
bufio,,,17,,,,,,,,,,,,,,,,,,17,
bytes,,,43,,,,,,,,,,,,,,,,,,43,
clevergo.tech/clevergo,1,,,,,,,,,,,,,,1,,,,,,,
compress/bzip2,,,1,,,,,,,,,,,,,,,,,,1,
compress/flate,,,4,,,,,,,,,,,,,,,,,,4,
compress/gzip,,,3,,,,,,,,,,,,,,,,,,3,
compress/lzw,,,1,,,,,,,,,,,,,,,,,,1,
compress/zlib,,,4,,,,,,,,,,,,,,,,,,4,
container/heap,,,5,,,,,,,,,,,,,,,,,,5,
container/list,,,20,,,,,,,,,,,,,,,,,,20,
container/ring,,,5,,,,,,,,,,,,,,,,,,5,
context,,,5,,,,,,,,,,,,,,,,,,5,
crypto,,,10,,,,,,,,,,,,,,,,,,10,
database/sql,,,11,,,,,,,,,,,,,,,,,,11,
encoding,,,77,,,,,,,,,,,,,,,,,,77,
errors,,,3,,,,,,,,,,,,,,,,,,3,
expvar,,,6,,,,,,,,,,,,,,,,,,6,
fmt,,,16,,,,,,,,,,,,,,,,,,16,
github.com/ChrisTrenkamp/goxpath,3,,,,,,,,,,,,,,,3,,,,,,
github.com/antchfx/htmlquery,4,,,,,,,,,,,,,,,4,,,,,,
github.com/antchfx/jsonquery,4,,,,,,,,,,,,,,,4,,,,,,
github.com/antchfx/xmlquery,8,,,,,,,,,,,,,,,8,,,,,,
github.com/antchfx/xpath,4,,,,,,,,,,,,,,,4,,,,,,
github.com/appleboy/gin-jwt,1,,,,1,,,,,,,,,,,,,,,,,
github.com/astaxie/beego,7,21,21,,,,5,,,,,,2,,,,,,21,,21,
github.com/beego/beego,14,42,42,,,,10,,,,,,4,,,,,,42,,42,
github.com/caarlos0/env,,5,2,,,,,,,,,,,,,,5,,,,1,1
github.com/clevergo/clevergo,1,,,,,,,,,,,,,,1,,,,,,,
github.com/codeskyblue/go-sh,4,,,4,,,,,,,,,,,,,,,,,,
github.com/couchbase/gocb,,,18,,,,,,,,,,,,,,,,,,18,
github.com/couchbaselabs/gocb,,,18,,,,,,,,,,,,,,,,,,18,
github.com/crankycoder/xmlpath,2,,,,,,,,,,,,,,,2,,,,,,
github.com/cristalhq/jwt,1,,,,1,,,,,,,,,,,,,,,,,
github.com/dgrijalva/jwt-go,3,,9,,2,1,,,,,,,,,,,,,,,9,
github.com/elazarl/goproxy,,2,2,,,,,,,,,,,,,,,,2,,2,
github.com/emicklei/go-restful,,7,,,,,,,,,,,,,,,,,7,,,
github.com/evanphx/json-patch,,,12,,,,,,,,,,,,,,,,,,12,
github.com/form3tech-oss/jwt-go,2,,,,2,,,,,,,,,,,,,,,,,
github.com/gin-gonic/gin,3,46,2,,,,3,,,,,,,,,,,,46,,2,
github.com/go-chi/chi,,3,,,,,,,,,,,,,,,,,3,,,
github.com/go-chi/jwtauth,1,,,,1,,,,,,,,,,,,,,,,,
github.com/go-jose/go-jose,3,,4,,2,1,,,,,,,,,,,,,,,4,
github.com/go-kit/kit/auth/jwt,1,,,,1,,,,,,,,,,,,,,,,,
github.com/go-pg/pg/orm,,,6,,,,,,,,,,,,,,,,,,6,
github.com/go-xmlpath/xmlpath,2,,,,,,,,,,,,,,,2,,,,,,
github.com/gobuffalo/envy,,7,,,,,,,,,,,,,,,7,,,,,
github.com/gobwas/ws,,2,,,,,,,,,,,,,,,,,2,,,
github.com/gofiber/fiber,5,,,,,,4,,,,,,,,1,,,,,,,
github.com/gogf/gf-jwt,1,,,,1,,,,,,,,,,,,,,,,,
github.com/going/toolkit/xmlpath,2,,,,,,,,,,,,,,,2,,,,,,
github.com/golang-jwt/jwt,3,,11,,2,1,,,,,,,,,,,,,,,11,
github.com/golang/protobuf/proto,,,4,,,,,,,,,,,,,,,,,,4,
github.com/gorilla/mux,,1,,,,,,,,,,,,,,,,,1,,,
github.com/gorilla/websocket,,3,,,,,,,,,,,,,,,,,3,,,
github.com/hashicorp/go-envparse,,1,,,,,,,,,,,,,,,1,,,,,
github.com/jbowtie/gokogiri/xml,4,,,,,,,,,,,,,,,4,,,,,,
github.com/jbowtie/gokogiri/xpath,1,,,,,,,,,,,,,,,1,,,,,,
github.com/joho/godotenv,,4,,,,,,,,,,,,,,,4,,,,,
github.com/json-iterator/go,,,4,,,,,,,,,,,,,,,,,,4,
github.com/kataras/iris/context,6,,,,,,6,,,,,,,,,,,,,,,
github.com/kataras/iris/middleware/jwt,2,,,,2,,,,,,,,,,,,,,,,,
github.com/kataras/iris/server/web/context,6,,,,,,6,,,,,,,,,,,,,,,
github.com/kataras/jwt,5,,,,5,,,,,,,,,,,,,,,,,
github.com/kelseyhightower/envconfig,,6,,,,,,,,,,,,,,,6,,,,,
github.com/labstack/echo,3,12,2,,,,2,,,,,,1,,,,,,12,,2,
github.com/lestrrat-go/jwx,2,,,,2,,,,,,,,,,,,,,,,,
github.com/lestrrat-go/libxml2/parser,3,,,,,,,,,,,,,,,3,,,,,,
github.com/lestrrat/go-jwx/jwk,1,,,,1,,,,,,,,,,,,,,,,,
github.com/masterzen/xmlpath,2,,,,,,,,,,,,,,,2,,,,,,
github.com/moovweb/gokogiri/xml,4,,,,,,,,,,,,,,,4,,,,,,
github.com/moovweb/gokogiri/xpath,1,,,,,,,,,,,,,,,1,,,,,,
github.com/ory/fosite/token/jwt,2,,,,2,,,,,,,,,,,,,,,,,
github.com/revel/revel,2,23,10,,,,1,,,,,,1,,,,,,23,,10,
github.com/robfig/revel,2,23,10,,,,1,,,,,,1,,,,,,23,,10,
github.com/santhosh-tekuri/xpathparser,2,,,,,,,,,,,,,,,2,,,,,,
github.com/sendgrid/sendgrid-go/helpers/mail,,,1,,,,,,,,,,,,,,,,,,1,
github.com/spf13/afero,34,,,,,,34,,,,,,,,,,,,,,,
github.com/square/go-jose,3,,4,,2,1,,,,,,,,,,,,,,,4,
github.com/valyala/fasthttp,35,50,5,,,,8,,,,17,8,2,,,,,,50,,5,
go.uber.org/zap,,,11,,,,,,,,,,,,,,,,,,11,
golang.org/x/crypto/ssh,4,,,4,,,,,,,,,,,,,,,,,,
golang.org/x/net/context,,,5,,,,,,,,,,,,,,,,,,5,
golang.org/x/net/html,,,16,,,,,,,,,,,,,,,,,,16,
golang.org/x/net/websocket,,2,,,,,,,,,,,,,,,,,2,,,
google.golang.org/protobuf/internal/encoding/text,,,1,,,,,,,,,,,,,,,,,,1,
google.golang.org/protobuf/internal/impl,,,2,,,,,,,,,,,,,,,,,,2,
google.golang.org/protobuf/proto,,,8,,,,,,,,,,,,,,,,,,8,
google.golang.org/protobuf/reflect/protoreflect,,,1,,,,,,,,,,,,,,,,,,1,
gopkg.in/couchbase/gocb,,,18,,,,,,,,,,,,,,,,,,18,
gopkg.in/go-jose/go-jose,3,,4,,2,1,,,,,,,,,,,,,,,4,
gopkg.in/go-xmlpath/xmlpath,2,,,,,,,,,,,,,,,2,,,,,,
gopkg.in/macaron,1,12,1,,,,,,,,,,,,1,,,,12,,1,
gopkg.in/square/go-jose,3,,4,,2,1,,,,,,,,,,,,,,,4,
gopkg.in/xmlpath,2,,,,,,,,,,,,,,,2,,,,,,
gopkg.in/yaml,,,9,,,,,,,,,,,,,,,,,,9,
html,,,8,,,,,,,,,,,,,,,,,,8,
io,5,4,34,,,,5,,,,,,,,,,,4,,,34,
k8s.io/api/core,,,10,,,,,,,,,,,,,,,,,,10,
k8s.io/apimachinery/pkg/runtime,,,47,,,,,,,,,,,,,,,,,,47,
launchpad.net/xmlpath,2,,,,,,,,,,,,,,,2,,,,,,
log,,,3,,,,,,,,,,,,,,,,,,3,
math/big,,,1,,,,,,,,,,,,,,,,,,1,
mime,,,14,,,,,,,,,,,,,,,,,,14,
net,2,16,100,,,,1,,,,,,,1,,,,,16,,100,
nhooyr.io/websocket,,2,,,,,,,,,,,,,,,,,2,,,
os,29,11,6,3,,,26,,,,,,,,,,7,3,,1,6,
path,,,18,,,,,,,,,,,,,,,,,,18,
reflect,,,37,,,,,,,,,,,,,,,,,,37,
regexp,10,,20,,,,,3,3,4,,,,,,,,,,,20,
sort,,,1,,,,,,,,,,,,,,,,,,1,
strconv,,,9,,,,,,,,,,,,,,,,,,9,
strings,,,34,,,,,,,,,,,,,,,,,,34,
sync,,,34,,,,,,,,,,,,,,,,,,34,
syscall,5,2,8,5,,,,,,,,,,,,,2,,,,8,
text/scanner,,,3,,,,,,,,,,,,,,,,,,3,
text/tabwriter,,,1,,,,,,,,,,,,,,,,,,1,
text/template,,,6,,,,,,,,,,,,,,,,,,6,
package,sink,source,summary,sink:command-injection,sink:credentials-key,sink:jwt,sink:log-injection,sink:nosql-injection,sink:path-injection,sink:regex-use[0],sink:regex-use[1],sink:regex-use[c],sink:request-forgery,sink:request-forgery[TCP Addr + Port],sink:sql-injection,sink:url-redirection,sink:url-redirection[0],sink:url-redirection[receiver],sink:xpath-injection,source:environment,source:file,source:remote,source:stdin,summary:taint,summary:value
,,,8,,,,,,,,,,,,,,,,,,,,,3,5
archive/tar,,,5,,,,,,,,,,,,,,,,,,,,,5,
archive/zip,,,6,,,,,,,,,,,,,,,,,,,,,6,
bufio,,,17,,,,,,,,,,,,,,,,,,,,,17,
bytes,,,43,,,,,,,,,,,,,,,,,,,,,43,
clevergo.tech/clevergo,1,,,,,,,,,,,,,,,,,1,,,,,,,
compress/bzip2,,,1,,,,,,,,,,,,,,,,,,,,,1,
compress/flate,,,4,,,,,,,,,,,,,,,,,,,,,4,
compress/gzip,,,3,,,,,,,,,,,,,,,,,,,,,3,
compress/lzw,,,1,,,,,,,,,,,,,,,,,,,,,1,
compress/zlib,,,4,,,,,,,,,,,,,,,,,,,,,4,
container/heap,,,5,,,,,,,,,,,,,,,,,,,,,5,
container/list,,,20,,,,,,,,,,,,,,,,,,,,,20,
container/ring,,,5,,,,,,,,,,,,,,,,,,,,,5,
context,,,5,,,,,,,,,,,,,,,,,,,,,5,
crypto,,,10,,,,,,,,,,,,,,,,,,,,,10,
database/sql,30,,11,,,,,,,,,,,,30,,,,,,,,,11,
encoding,,,77,,,,,,,,,,,,,,,,,,,,,77,
errors,,,3,,,,,,,,,,,,,,,,,,,,,3,
expvar,,,6,,,,,,,,,,,,,,,,,,,,,6,
fmt,3,,16,,,,3,,,,,,,,,,,,,,,,,16,
github.com/ChrisTrenkamp/goxpath,3,,,,,,,,,,,,,,,,,,3,,,,,,
github.com/Masterminds/squirrel,32,,,,,,,,,,,,,,32,,,,,,,,,,
github.com/Sirupsen/logrus,145,,,,,,145,,,,,,,,,,,,,,,,,,
github.com/antchfx/htmlquery,4,,,,,,,,,,,,,,,,,,4,,,,,,
github.com/antchfx/jsonquery,4,,,,,,,,,,,,,,,,,,4,,,,,,
github.com/antchfx/xmlquery,8,,,,,,,,,,,,,,,,,,8,,,,,,
github.com/antchfx/xpath,4,,,,,,,,,,,,,,,,,,4,,,,,,
github.com/appleboy/gin-jwt,1,,,,1,,,,,,,,,,,,,,,,,,,,
github.com/astaxie/beego,71,21,21,,,,34,,5,,,,,,30,2,,,,,,21,,21,
github.com/beego/beego,142,42,42,,,,68,,10,,,,,,60,4,,,,,,42,,42,
github.com/caarlos0/env,,5,2,,,,,,,,,,,,,,,,,5,,,,1,1
github.com/clevergo/clevergo,1,,,,,,,,,,,,,,,,,1,,,,,,,
github.com/codeskyblue/go-sh,4,,,4,,,,,,,,,,,,,,,,,,,,,
github.com/couchbase/gocb,8,,18,,,,,8,,,,,,,,,,,,,,,,18,
github.com/couchbaselabs/gocb,8,,18,,,,,8,,,,,,,,,,,,,,,,18,
github.com/crankycoder/xmlpath,2,,,,,,,,,,,,,,,,,,2,,,,,,
github.com/cristalhq/jwt,1,,,,1,,,,,,,,,,,,,,,,,,,,
github.com/davecgh/go-spew/spew,9,,,,,,9,,,,,,,,,,,,,,,,,,
github.com/dgrijalva/jwt-go,3,,9,,2,1,,,,,,,,,,,,,,,,,,9,
github.com/elazarl/goproxy,2,2,2,,,,2,,,,,,,,,,,,,,,2,,2,
github.com/emicklei/go-restful,,7,,,,,,,,,,,,,,,,,,,,7,,,
github.com/evanphx/json-patch,,,12,,,,,,,,,,,,,,,,,,,,,12,
github.com/form3tech-oss/jwt-go,2,,,,2,,,,,,,,,,,,,,,,,,,,
github.com/gin-gonic/gin,3,46,2,,,,,,3,,,,,,,,,,,,,46,,2,
github.com/go-chi/chi,,3,,,,,,,,,,,,,,,,,,,,3,,,
github.com/go-chi/jwtauth,1,,,,1,,,,,,,,,,,,,,,,,,,,
github.com/go-gorm/gorm,13,,,,,,,,,,,,,,13,,,,,,,,,,
github.com/go-jose/go-jose,3,,4,,2,1,,,,,,,,,,,,,,,,,,4,
github.com/go-kit/kit/auth/jwt,1,,,,1,,,,,,,,,,,,,,,,,,,,
github.com/go-pg/pg/orm,,,6,,,,,,,,,,,,,,,,,,,,,6,
github.com/go-xmlpath/xmlpath,2,,,,,,,,,,,,,,,,,,2,,,,,,
github.com/go-xorm/xorm,34,,,,,,,,,,,,,,34,,,,,,,,,,
github.com/gobuffalo/envy,,7,,,,,,,,,,,,,,,,,,7,,,,,
github.com/gobwas/ws,,2,,,,,,,,,,,,,,,,,,,,2,,,
github.com/gofiber/fiber,5,,,,,,,,4,,,,,,,,,1,,,,,,,
github.com/gogf/gf-jwt,1,,,,1,,,,,,,,,,,,,,,,,,,,
github.com/gogf/gf/database/gdb,51,,,,,,,,,,,,,,51,,,,,,,,,,
github.com/going/toolkit/xmlpath,2,,,,,,,,,,,,,,,,,,2,,,,,,
github.com/golang-jwt/jwt,3,,11,,2,1,,,,,,,,,,,,,,,,,,11,
github.com/golang/glog,90,,,,,,90,,,,,,,,,,,,,,,,,,
github.com/golang/protobuf/proto,,,4,,,,,,,,,,,,,,,,,,,,,4,
github.com/gorilla/mux,,1,,,,,,,,,,,,,,,,,,,,1,,,
github.com/gorilla/websocket,,3,,,,,,,,,,,,,,,,,,,,3,,,
github.com/hashicorp/go-envparse,,1,,,,,,,,,,,,,,,,,,1,,,,,
github.com/jbowtie/gokogiri/xml,4,,,,,,,,,,,,,,,,,,4,,,,,,
github.com/jbowtie/gokogiri/xpath,1,,,,,,,,,,,,,,,,,,1,,,,,,
github.com/jinzhu/gorm,13,,,,,,,,,,,,,,13,,,,,,,,,,
github.com/jmoiron/sqlx,12,,,,,,,,,,,,,,12,,,,,,,,,,
github.com/joho/godotenv,,4,,,,,,,,,,,,,,,,,,4,,,,,
github.com/json-iterator/go,,,4,,,,,,,,,,,,,,,,,,,,,4,
github.com/kataras/iris/context,6,,,,,,,,6,,,,,,,,,,,,,,,,
github.com/kataras/iris/middleware/jwt,2,,,,2,,,,,,,,,,,,,,,,,,,,
github.com/kataras/iris/server/web/context,6,,,,,,,,6,,,,,,,,,,,,,,,,
github.com/kataras/jwt,5,,,,5,,,,,,,,,,,,,,,,,,,,
github.com/kelseyhightower/envconfig,,6,,,,,,,,,,,,,,,,,,6,,,,,
github.com/labstack/echo,3,12,2,,,,,,2,,,,,,,1,,,,,,12,,2,
github.com/lann/squirrel,32,,,,,,,,,,,,,,32,,,,,,,,,,
github.com/lestrrat-go/jwx,2,,,,2,,,,,,,,,,,,,,,,,,,,
github.com/lestrrat-go/libxml2/parser,3,,,,,,,,,,,,,,,,,,3,,,,,,
github.com/lestrrat/go-jwx/jwk,1,,,,1,,,,,,,,,,,,,,,,,,,,
github.com/masterzen/xmlpath,2,,,,,,,,,,,,,,,,,,2,,,,,,
github.com/moovweb/gokogiri/xml,4,,,,,,,,,,,,,,,,,,4,,,,,,
github.com/moovweb/gokogiri/xpath,1,,,,,,,,,,,,,,,,,,1,,,,,,
github.com/ory/fosite/token/jwt,2,,,,2,,,,,,,,,,,,,,,,,,,,
github.com/raindog308/gorqlite,24,,,,,,,,,,,,,,24,,,,,,,,,,
github.com/revel/revel,2,23,10,,,,,,1,,,,,,,1,,,,,,23,,10,
github.com/robfig/revel,2,23,10,,,,,,1,,,,,,,1,,,,,,23,,10,
github.com/rqlite/gorqlite,24,,,,,,,,,,,,,,24,,,,,,,,,,
github.com/santhosh-tekuri/xpathparser,2,,,,,,,,,,,,,,,,,,2,,,,,,
github.com/sendgrid/sendgrid-go/helpers/mail,,,1,,,,,,,,,,,,,,,,,,,,,1,
github.com/sirupsen/logrus,145,,,,,,145,,,,,,,,,,,,,,,,,,
github.com/spf13/afero,34,,,,,,,,34,,,,,,,,,,,,,,,,
github.com/square/go-jose,3,,4,,2,1,,,,,,,,,,,,,,,,,,4,
github.com/uptrace/bun,63,,,,,,,,,,,,,,63,,,,,,,,,,
github.com/valyala/fasthttp,35,50,5,,,,,,8,,,,17,8,,2,,,,,,50,,5,
go.mongodb.org/mongo-driver/mongo,14,,,,,,,14,,,,,,,,,,,,,,,,,
go.uber.org/zap,33,,11,,,,33,,,,,,,,,,,,,,,,,11,
golang.org/x/crypto/ssh,4,,,4,,,,,,,,,,,,,,,,,,,,,
golang.org/x/net/context,,,5,,,,,,,,,,,,,,,,,,,,,5,
golang.org/x/net/html,,,16,,,,,,,,,,,,,,,,,,,,,16,
golang.org/x/net/websocket,,2,,,,,,,,,,,,,,,,,,,,2,,,
google.golang.org/protobuf/internal/encoding/text,,,1,,,,,,,,,,,,,,,,,,,,,1,
google.golang.org/protobuf/internal/impl,,,2,,,,,,,,,,,,,,,,,,,,,2,
google.golang.org/protobuf/proto,,,8,,,,,,,,,,,,,,,,,,,,,8,
google.golang.org/protobuf/reflect/protoreflect,,,1,,,,,,,,,,,,,,,,,,,,,1,
gopkg.in/Masterminds/squirrel,32,,,,,,,,,,,,,,32,,,,,,,,,,
gopkg.in/couchbase/gocb,8,,18,,,,,8,,,,,,,,,,,,,,,,18,
gopkg.in/glog,90,,,,,,90,,,,,,,,,,,,,,,,,,
gopkg.in/go-jose/go-jose,3,,4,,2,1,,,,,,,,,,,,,,,,,,4,
gopkg.in/go-xmlpath/xmlpath,2,,,,,,,,,,,,,,,,,,2,,,,,,
gopkg.in/macaron,1,12,1,,,,,,,,,,,,,,,1,,,,12,,1,
gopkg.in/square/go-jose,3,,4,,2,1,,,,,,,,,,,,,,,,,,4,
gopkg.in/xmlpath,2,,,,,,,,,,,,,,,,,,2,,,,,,
gopkg.in/yaml,,,9,,,,,,,,,,,,,,,,,,,,,9,
gorm.io/gorm,13,,,,,,,,,,,,,,13,,,,,,,,,,
html,,,8,,,,,,,,,,,,,,,,,,,,,8,
io,5,4,34,,,,,,5,,,,,,,,,,,,4,,,34,
k8s.io/api/core,,,10,,,,,,,,,,,,,,,,,,,,,10,
k8s.io/apimachinery/pkg/runtime,,,47,,,,,,,,,,,,,,,,,,,,,47,
k8s.io/klog,90,,,,,,90,,,,,,,,,,,,,,,,,,
launchpad.net/xmlpath,2,,,,,,,,,,,,,,,,,,2,,,,,,
log,20,,3,,,,20,,,,,,,,,,,,,,,,,3,
math/big,,,1,,,,,,,,,,,,,,,,,,,,,1,
mime,,,14,,,,,,,,,,,,,,,,,,,,,14,
net,2,16,100,,,,,,1,,,,,,,,1,,,,,16,,100,
nhooyr.io/websocket,,2,,,,,,,,,,,,,,,,,,,,2,,,
os,29,11,6,3,,,,,26,,,,,,,,,,,7,3,,1,6,
path,,,18,,,,,,,,,,,,,,,,,,,,,18,
reflect,,,37,,,,,,,,,,,,,,,,,,,,,37,
regexp,10,,20,,,,,,,3,3,4,,,,,,,,,,,,20,
sort,,,1,,,,,,,,,,,,,,,,,,,,,1,
strconv,,,9,,,,,,,,,,,,,,,,,,,,,9,
strings,,,34,,,,,,,,,,,,,,,,,,,,,34,
sync,,,34,,,,,,,,,,,,,,,,,,,,,34,
syscall,5,2,8,5,,,,,,,,,,,,,,,,2,,,,8,
text/scanner,,,3,,,,,,,,,,,,,,,,,,,,,3,
text/tabwriter,,,1,,,,,,,,,,,,,,,,,,,,,1,
text/template,,,6,,,,,,,,,,,,,,,,,,,,,6,
xorm.io/xorm,34,,,,,,,,,,,,,,34,,,,,,,,,,
1 package sink source summary sink:command-injection sink:credentials-key sink:jwt sink:log-injection sink:nosql-injection sink:path-injection sink:regex-use[0] sink:regex-use[1] sink:regex-use[c] sink:request-forgery sink:request-forgery[TCP Addr + Port] sink:sql-injection sink:url-redirection sink:url-redirection[0] sink:url-redirection[receiver] sink:xpath-injection source:environment source:file source:remote source:stdin summary:taint summary:value
2 8 3 5
3 archive/tar 5 5
4 archive/zip 6 6
5 bufio 17 17
6 bytes 43 43
7 clevergo.tech/clevergo 1 1
8 compress/bzip2 1 1
9 compress/flate 4 4
10 compress/gzip 3 3
11 compress/lzw 1 1
12 compress/zlib 4 4
13 container/heap 5 5
14 container/list 20 20
15 container/ring 5 5
16 context 5 5
17 crypto 10 10
18 database/sql 30 11 30 11
19 encoding 77 77
20 errors 3 3
21 expvar 6 6
22 fmt 3 16 3 16
23 github.com/ChrisTrenkamp/goxpath 3 3
24 github.com/antchfx/htmlquery github.com/Masterminds/squirrel 4 32 32 4
25 github.com/antchfx/jsonquery github.com/Sirupsen/logrus 4 145 145 4
26 github.com/antchfx/xmlquery github.com/antchfx/htmlquery 8 4 8 4
27 github.com/antchfx/xpath github.com/antchfx/jsonquery 4 4
28 github.com/appleboy/gin-jwt github.com/antchfx/xmlquery 1 8 1 8
29 github.com/astaxie/beego github.com/antchfx/xpath 7 4 21 21 5 2 4 21 21
30 github.com/beego/beego github.com/appleboy/gin-jwt 14 1 42 42 1 10 4 42 42
31 github.com/caarlos0/env github.com/astaxie/beego 71 5 21 2 21 34 5 30 2 5 21 1 21 1
32 github.com/clevergo/clevergo github.com/beego/beego 1 142 42 42 68 10 60 4 1 42 42
33 github.com/codeskyblue/go-sh github.com/caarlos0/env 4 5 2 4 5 1 1
34 github.com/couchbase/gocb github.com/clevergo/clevergo 1 18 1 18
35 github.com/couchbaselabs/gocb github.com/codeskyblue/go-sh 4 18 4 18
36 github.com/crankycoder/xmlpath github.com/couchbase/gocb 2 8 18 8 2 18
37 github.com/cristalhq/jwt github.com/couchbaselabs/gocb 1 8 18 1 8 18
38 github.com/dgrijalva/jwt-go github.com/crankycoder/xmlpath 3 2 9 2 1 2 9
39 github.com/elazarl/goproxy github.com/cristalhq/jwt 1 2 2 1 2 2
40 github.com/emicklei/go-restful github.com/davecgh/go-spew/spew 9 7 9 7
41 github.com/evanphx/json-patch github.com/dgrijalva/jwt-go 3 12 9 2 1 12 9
42 github.com/form3tech-oss/jwt-go github.com/elazarl/goproxy 2 2 2 2 2 2 2
43 github.com/gin-gonic/gin github.com/emicklei/go-restful 3 46 7 2 3 46 7 2
44 github.com/go-chi/chi github.com/evanphx/json-patch 3 12 3 12
45 github.com/go-chi/jwtauth github.com/form3tech-oss/jwt-go 1 2 1 2
46 github.com/go-jose/go-jose github.com/gin-gonic/gin 3 46 4 2 2 1 3 46 4 2
47 github.com/go-kit/kit/auth/jwt github.com/go-chi/chi 1 3 1 3
48 github.com/go-pg/pg/orm github.com/go-chi/jwtauth 1 6 1 6
49 github.com/go-xmlpath/xmlpath github.com/go-gorm/gorm 2 13 13 2
50 github.com/gobuffalo/envy github.com/go-jose/go-jose 3 7 4 2 1 7 4
51 github.com/gobwas/ws github.com/go-kit/kit/auth/jwt 1 2 1 2
52 github.com/gofiber/fiber github.com/go-pg/pg/orm 5 6 4 1 6
53 github.com/gogf/gf-jwt github.com/go-xmlpath/xmlpath 1 2 1 2
54 github.com/going/toolkit/xmlpath github.com/go-xorm/xorm 2 34 34 2
55 github.com/golang-jwt/jwt github.com/gobuffalo/envy 3 7 11 2 1 7 11
56 github.com/golang/protobuf/proto github.com/gobwas/ws 2 4 2 4
57 github.com/gorilla/mux github.com/gofiber/fiber 5 1 4 1 1
58 github.com/gorilla/websocket github.com/gogf/gf-jwt 1 3 1 3
59 github.com/hashicorp/go-envparse github.com/gogf/gf/database/gdb 51 1 51 1
60 github.com/jbowtie/gokogiri/xml github.com/going/toolkit/xmlpath 4 2 4 2
61 github.com/jbowtie/gokogiri/xpath github.com/golang-jwt/jwt 1 3 11 2 1 1 11
62 github.com/joho/godotenv github.com/golang/glog 90 4 90 4
63 github.com/json-iterator/go github.com/golang/protobuf/proto 4 4
64 github.com/kataras/iris/context github.com/gorilla/mux 6 1 6 1
65 github.com/kataras/iris/middleware/jwt github.com/gorilla/websocket 2 3 2 3
66 github.com/kataras/iris/server/web/context github.com/hashicorp/go-envparse 6 1 6 1
67 github.com/kataras/jwt github.com/jbowtie/gokogiri/xml 5 4 5 4
68 github.com/kelseyhightower/envconfig github.com/jbowtie/gokogiri/xpath 1 6 1 6
69 github.com/labstack/echo github.com/jinzhu/gorm 3 13 12 2 2 13 1 12 2
70 github.com/lestrrat-go/jwx github.com/jmoiron/sqlx 2 12 2 12
71 github.com/lestrrat-go/libxml2/parser github.com/joho/godotenv 3 4 3 4
72 github.com/lestrrat/go-jwx/jwk github.com/json-iterator/go 1 4 1 4
73 github.com/masterzen/xmlpath github.com/kataras/iris/context 2 6 6 2
74 github.com/moovweb/gokogiri/xml github.com/kataras/iris/middleware/jwt 4 2 2 4
75 github.com/moovweb/gokogiri/xpath github.com/kataras/iris/server/web/context 1 6 6 1
76 github.com/ory/fosite/token/jwt github.com/kataras/jwt 2 5 2 5
77 github.com/revel/revel github.com/kelseyhightower/envconfig 2 23 6 10 1 1 6 23 10
78 github.com/robfig/revel github.com/labstack/echo 2 3 23 12 10 2 1 2 1 23 12 10 2
79 github.com/santhosh-tekuri/xpathparser github.com/lann/squirrel 2 32 32 2
80 github.com/sendgrid/sendgrid-go/helpers/mail github.com/lestrrat-go/jwx 2 1 2 1
81 github.com/spf13/afero github.com/lestrrat-go/libxml2/parser 34 3 34 3
82 github.com/square/go-jose github.com/lestrrat/go-jwx/jwk 3 1 4 2 1 1 4
83 github.com/valyala/fasthttp github.com/masterzen/xmlpath 35 2 50 5 8 17 8 2 2 50 5
84 go.uber.org/zap github.com/moovweb/gokogiri/xml 4 11 4 11
85 golang.org/x/crypto/ssh github.com/moovweb/gokogiri/xpath 4 1 4 1
86 golang.org/x/net/context github.com/ory/fosite/token/jwt 2 5 2 5
87 golang.org/x/net/html github.com/raindog308/gorqlite 24 16 24 16
88 golang.org/x/net/websocket github.com/revel/revel 2 2 23 10 1 1 2 23 10
89 google.golang.org/protobuf/internal/encoding/text github.com/robfig/revel 2 23 1 10 1 1 23 1 10
90 google.golang.org/protobuf/internal/impl github.com/rqlite/gorqlite 24 2 24 2
91 google.golang.org/protobuf/proto github.com/santhosh-tekuri/xpathparser 2 8 2 8
92 google.golang.org/protobuf/reflect/protoreflect github.com/sendgrid/sendgrid-go/helpers/mail 1 1
93 gopkg.in/couchbase/gocb github.com/sirupsen/logrus 145 18 145 18
94 gopkg.in/go-jose/go-jose github.com/spf13/afero 3 34 4 2 1 34 4
95 gopkg.in/go-xmlpath/xmlpath github.com/square/go-jose 2 3 4 2 1 2 4
96 gopkg.in/macaron github.com/uptrace/bun 1 63 12 1 63 1 12 1
97 gopkg.in/square/go-jose github.com/valyala/fasthttp 3 35 50 4 5 2 1 8 17 8 2 50 4 5
98 gopkg.in/xmlpath go.mongodb.org/mongo-driver/mongo 2 14 14 2
99 gopkg.in/yaml go.uber.org/zap 33 9 11 33 9 11
100 html golang.org/x/crypto/ssh 4 8 4 8
101 io golang.org/x/net/context 5 4 34 5 5 4 34 5
102 k8s.io/api/core golang.org/x/net/html 10 16 10 16
103 k8s.io/apimachinery/pkg/runtime golang.org/x/net/websocket 2 47 2 47
104 launchpad.net/xmlpath google.golang.org/protobuf/internal/encoding/text 2 1 2 1
105 log google.golang.org/protobuf/internal/impl 3 2 3 2
106 math/big google.golang.org/protobuf/proto 1 8 1 8
107 mime google.golang.org/protobuf/reflect/protoreflect 14 1 14 1
108 net gopkg.in/Masterminds/squirrel 2 32 16 100 1 32 1 16 100
109 nhooyr.io/websocket gopkg.in/couchbase/gocb 8 2 18 8 2 18
110 os gopkg.in/glog 29 90 11 6 3 90 26 7 3 1 6
111 path gopkg.in/go-jose/go-jose 3 18 4 2 1 18 4
112 reflect gopkg.in/go-xmlpath/xmlpath 2 37 2 37
113 regexp gopkg.in/macaron 10 1 12 20 1 3 3 4 1 12 20 1
114 sort gopkg.in/square/go-jose 3 1 4 2 1 1 4
115 strconv gopkg.in/xmlpath 2 9 2 9
116 strings gopkg.in/yaml 34 9 34 9
117 sync gorm.io/gorm 13 34 13 34
118 syscall html 5 2 8 5 2 8
119 text/scanner io 5 4 3 34 5 4 3 34
120 text/tabwriter k8s.io/api/core 1 10 1 10
121 text/template k8s.io/apimachinery/pkg/runtime 6 47 6 47
122 k8s.io/klog 90 90
123 launchpad.net/xmlpath 2 2
124 log 20 3 20 3
125 math/big 1 1
126 mime 14 14
127 net 2 16 100 1 1 16 100
128 nhooyr.io/websocket 2 2
129 os 29 11 6 3 26 7 3 1 6
130 path 18 18
131 reflect 37 37
132 regexp 10 20 3 3 4 20
133 sort 1 1
134 strconv 9 9
135 strings 34 34
136 sync 34 34
137 syscall 5 2 8 5 2 8
138 text/scanner 3 3
139 text/tabwriter 1 1
140 text/template 6 6
141 xorm.io/xorm 34 34

View File

@@ -9,27 +9,27 @@ Go framework & library support
Framework / library,Package,Flow sources,Taint & value steps,Sinks (total)
`Afero <https://github.com/spf13/afero>`_,``github.com/spf13/afero*``,,,34
`CleverGo <https://github.com/clevergo/clevergo>`_,"``clevergo.tech/clevergo*``, ``github.com/clevergo/clevergo*``",,,2
`Couchbase official client(gocb) <https://github.com/couchbase/gocb>`_,"``github.com/couchbase/gocb*``, ``gopkg.in/couchbase/gocb*``",,36,
`Couchbase unofficial client <http://www.github.com/couchbase/go-couchbase>`_,``github.com/couchbaselabs/gocb*``,,18,
`Couchbase official client(gocb) <https://github.com/couchbase/gocb>`_,"``github.com/couchbase/gocb*``, ``gopkg.in/couchbase/gocb*``",,36,16
`Couchbase unofficial client <http://www.github.com/couchbase/go-couchbase>`_,``github.com/couchbaselabs/gocb*``,,18,8
`Echo <https://echo.labstack.com/>`_,``github.com/labstack/echo*``,12,2,3
`Fiber <https://github.com/gofiber/fiber>`_,``github.com/gofiber/fiber*``,,,5
`Fosite <https://github.com/ory/fosite>`_,``github.com/ory/fosite*``,,,2
`Gin <https://github.com/gin-gonic/gin>`_,``github.com/gin-gonic/gin*``,46,2,3
`Glog <https://github.com/golang/glog>`_,"``github.com/golang/glog*``, ``gopkg.in/glog*``, ``k8s.io/klog*``",,,
`Glog <https://github.com/golang/glog>`_,"``github.com/golang/glog*``, ``gopkg.in/glog*``, ``k8s.io/klog*``",,,270
`Go JOSE <https://github.com/go-jose/go-jose>`_,"``github.com/go-jose/go-jose*``, ``github.com/square/go-jose*``, ``gopkg.in/square/go-jose*``, ``gopkg.in/go-jose/go-jose*``",,16,12
`Go kit <https://gokit.io/>`_,``github.com/go-kit/kit*``,,,1
`Go-spew <https://github.com/davecgh/go-spew>`_,``github.com/davecgh/go-spew/spew*``,,,
`Go-spew <https://github.com/davecgh/go-spew>`_,``github.com/davecgh/go-spew/spew*``,,,9
`Gokogiri <https://github.com/moovweb/gokogiri>`_,"``github.com/jbowtie/gokogiri*``, ``github.com/moovweb/gokogiri*``",,,10
`Iris <https://www.iris-go.com/>`_,``github.com/kataras/iris*``,,,14
`Kubernetes <https://kubernetes.io/>`_,"``k8s.io/api*``, ``k8s.io/apimachinery*``",,57,
`Logrus <https://github.com/sirupsen/logrus>`_,"``github.com/Sirupsen/logrus*``, ``github.com/sirupsen/logrus*``",,,
`Logrus <https://github.com/sirupsen/logrus>`_,"``github.com/Sirupsen/logrus*``, ``github.com/sirupsen/logrus*``",,,290
`Macaron <https://gopkg.in/macaron.v1>`_,``gopkg.in/macaron*``,12,1,1
`Revel <http://revel.github.io/>`_,"``github.com/revel/revel*``, ``github.com/robfig/revel*``",46,20,4
`SendGrid <https://github.com/sendgrid/sendgrid-go>`_,``github.com/sendgrid/sendgrid-go*``,,1,
`Standard library <https://pkg.go.dev/std>`_,"````, ``archive/*``, ``bufio``, ``bytes``, ``cmp``, ``compress/*``, ``container/*``, ``context``, ``crypto``, ``crypto/*``, ``database/*``, ``debug/*``, ``embed``, ``encoding``, ``encoding/*``, ``errors``, ``expvar``, ``flag``, ``fmt``, ``go/*``, ``hash``, ``hash/*``, ``html``, ``html/*``, ``image``, ``image/*``, ``index/*``, ``io``, ``io/*``, ``log``, ``log/*``, ``maps``, ``math``, ``math/*``, ``mime``, ``mime/*``, ``net``, ``net/*``, ``os``, ``os/*``, ``path``, ``path/*``, ``plugin``, ``reflect``, ``reflect/*``, ``regexp``, ``regexp/*``, ``slices``, ``sort``, ``strconv``, ``strings``, ``sync``, ``sync/*``, ``syscall``, ``syscall/*``, ``testing``, ``testing/*``, ``text/*``, ``time``, ``time/*``, ``unicode``, ``unicode/*``, ``unsafe``",33,587,51
`Standard library <https://pkg.go.dev/std>`_,"````, ``archive/*``, ``bufio``, ``bytes``, ``cmp``, ``compress/*``, ``container/*``, ``context``, ``crypto``, ``crypto/*``, ``database/*``, ``debug/*``, ``embed``, ``encoding``, ``encoding/*``, ``errors``, ``expvar``, ``flag``, ``fmt``, ``go/*``, ``hash``, ``hash/*``, ``html``, ``html/*``, ``image``, ``image/*``, ``index/*``, ``io``, ``io/*``, ``log``, ``log/*``, ``maps``, ``math``, ``math/*``, ``mime``, ``mime/*``, ``net``, ``net/*``, ``os``, ``os/*``, ``path``, ``path/*``, ``plugin``, ``reflect``, ``reflect/*``, ``regexp``, ``regexp/*``, ``slices``, ``sort``, ``strconv``, ``strings``, ``sync``, ``sync/*``, ``syscall``, ``syscall/*``, ``testing``, ``testing/*``, ``text/*``, ``time``, ``time/*``, ``unicode``, ``unicode/*``, ``unsafe``",33,587,104
`XPath <https://github.com/antchfx/xpath>`_,``github.com/antchfx/xpath*``,,,4
`appleboy/gin-jwt <https://github.com/appleboy/gin-jwt>`_,``github.com/appleboy/gin-jwt*``,,,1
`beego <https://beego.me/>`_,"``github.com/astaxie/beego*``, ``github.com/beego/beego*``",63,63,21
`beego <https://beego.me/>`_,"``github.com/astaxie/beego*``, ``github.com/beego/beego*``",63,63,213
`chi <https://go-chi.io/>`_,``github.com/go-chi/chi*``,3,,
`cristalhq/jwt <https://github.com/cristalhq/jwt>`_,``github.com/cristalhq/jwt*``,,,1
`fasthttp <https://github.com/valyala/fasthttp>`_,``github.com/valyala/fasthttp*``,50,5,35
@@ -39,7 +39,7 @@ Go framework & library support
`go-sh <https://github.com/codeskyblue/go-sh>`_,``github.com/codeskyblue/go-sh*``,,,4
`golang.org/x/crypto/ssh <https://pkg.go.dev/golang.org/x/crypto/ssh>`_,``golang.org/x/crypto/ssh*``,,,4
`golang.org/x/net <https://pkg.go.dev/golang.org/x/net>`_,``golang.org/x/net*``,2,21,
`goproxy <https://github.com/elazarl/goproxy>`_,``github.com/elazarl/goproxy*``,2,2,
`goproxy <https://github.com/elazarl/goproxy>`_,``github.com/elazarl/goproxy*``,2,2,2
`gorilla/mux <https://github.com/gorilla/mux>`_,``github.com/gorilla/mux*``,1,,
`gorilla/websocket <https://github.com/gorilla/websocket>`_,``github.com/gorilla/websocket*``,3,,
`goxpath <https://github.com/ChrisTrenkamp/goxpath/wiki>`_,``github.com/ChrisTrenkamp/goxpath*``,,,3
@@ -59,7 +59,7 @@ Go framework & library support
`xmlquery <https://github.com/antchfx/xmlquery>`_,``github.com/antchfx/xmlquery*``,,,8
`xpathparser <https://github.com/santhosh-tekuri/xpathparser>`_,``github.com/santhosh-tekuri/xpathparser*``,,,2
`yaml <https://gopkg.in/yaml.v3>`_,``gopkg.in/yaml*``,,9,
`zap <https://go.uber.org/zap>`_,``go.uber.org/zap*``,,11,
Others,"``github.com/caarlos0/env``, ``github.com/gobuffalo/envy``, ``github.com/hashicorp/go-envparse``, ``github.com/joho/godotenv``, ``github.com/kelseyhightower/envconfig``",23,2,
Totals,,307,911,268
`zap <https://go.uber.org/zap>`_,``go.uber.org/zap*``,,11,33
Others,"``github.com/Masterminds/squirrel``, ``github.com/caarlos0/env``, ``github.com/go-gorm/gorm``, ``github.com/go-xorm/xorm``, ``github.com/gobuffalo/envy``, ``github.com/gogf/gf/database/gdb``, ``github.com/hashicorp/go-envparse``, ``github.com/jinzhu/gorm``, ``github.com/jmoiron/sqlx``, ``github.com/joho/godotenv``, ``github.com/kelseyhightower/envconfig``, ``github.com/lann/squirrel``, ``github.com/raindog308/gorqlite``, ``github.com/rqlite/gorqlite``, ``github.com/uptrace/bun``, ``go.mongodb.org/mongo-driver/mongo``, ``gopkg.in/Masterminds/squirrel``, ``gorm.io/gorm``, ``xorm.io/xorm``",23,2,391
Totals,,307,911,1532

View File

@@ -1,197 +0,0 @@
#!/bin/bash
set -e
help="Usage: ./publish [--override-release] [--dry-run]
Publish the automodel query pack.
If no arguments are provided, publish the version of the codeql repo specified by the latest official release of the codeml-automodel repo.
If the --override-release argument is provided, your current local HEAD is used (for unofficial releases or patching).
If the --dry-run argument is provided, the release is not published (for testing purposes)."
# Echo the help message
if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
echo "$help"
exit 0
fi
# Check the number of arguments are valid
if [ $# -gt 2 ]; then
echo "Error: Invalid arguments provided"
echo "$help"
exit 1
fi
OVERRIDE_RELEASE=0
DRY_RUN=0
for arg in "$@"
do
case $arg in
--override-release)
OVERRIDE_RELEASE=1
shift # Remove --override-release from processing
;;
--dry-run)
DRY_RUN=1
shift # Remove --dry-run from processing
;;
*)
echo "Error: Invalid argument provided: $arg"
echo "$help"
exit 1
;;
esac
done
# Describe what we're about to do based on the command-line arguments
if [ $OVERRIDE_RELEASE = 1 ]; then
echo "Publishing the current HEAD of the automodel repo"
else
echo "Publishing the version of the automodel repo specified by the latest official release of the codeml-automodel repo"
fi
if [ $DRY_RUN = 1 ]; then
echo "Dry run: we will step through the process but we won't publish the query pack"
else
echo "Not a dry run! Publishing the query pack"
fi
# If we're publishing the codeml-automodel release then we will checkout the sha specified in the release.
# So we need to check that there are no uncommitted changes in the local branch.
# And, if we're publishing the current HEAD, it's cleaner to ensure that there are no uncommitted changes.
if ! git diff --quiet; then
echo "Error: Uncommitted changes exist. Please commit or stash your changes before publishing."
exit 1
fi
# Check the above environment variables are set
if [ -z "${GITHUB_TOKEN}" ]; then
echo "Error: GITHUB_TOKEN environment variable not set. Please set this to a token with package:write permissions to codeql."
exit 1
fi
if [ -z "${GH_TOKEN}" ]; then
echo "Error: GH_TOKEN environment variable not set. Please set this to a token with repo permissions to github/codeml-automodel."
exit 1
fi
# Get the sha of the previous release, i.e. the last commit to the main branch that updated the query pack version
PREVIOUS_RELEASE_SHA=$(git rev-list -n 1 main -- ./src/qlpack.yml)
if [ -z "$PREVIOUS_RELEASE_SHA" ]; then
echo "Error: Could not get the sha of the previous release of codeml-automodel query pack"
exit 1
else
echo "Previous query-pack release sha: $PREVIOUS_RELEASE_SHA"
fi
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
CURRENT_SHA=$(git rev-parse HEAD)
if [ $OVERRIDE_RELEASE = 1 ]; then
# Check that the current HEAD is downstream from PREVIOUS_RELEASE_SHA
if ! git merge-base --is-ancestor "$PREVIOUS_RELEASE_SHA" "$CURRENT_SHA"; then
echo "Error: The current HEAD is not downstream from the previous release"
exit 1
fi
else
# Get the latest release of codeml-automodel
TAG_NAME=$(gh api -H 'Accept: application/vnd.github+json' -H 'X-GitHub-Api-Version: 2022-11-28' /repos/github/codeml-automodel/releases/latest | jq -r .tag_name)
# Check TAG_NAME is not empty
if [ -z "$TAG_NAME" ]; then
echo "Error: Could not get latest release of codeml-automodel"
exit 1
fi
echo "Updating to latest automodel release: $TAG_NAME"
# Before downloading, delete any existing release.zip, and ignore failure if not present
rm release.zip || true
gh release download $TAG_NAME -A zip -O release.zip --repo 'https://github.com/github/codeml-automodel'
# Before unzipping, delete any existing release directory, and ignore failure if not present
rm -rf release || true
unzip -o release.zip -d release
REVISION=$(jq -r '.["codeql-sha"]' release/codeml-automodel*/codeml-automodel-release.json)
echo "The latest codeml-automodel release specifies the codeql sha $REVISION"
# Check that REVISION is downstream from PREVIOUS_RELEASE_SHA
if ! git merge-base --is-ancestor "$PREVIOUS_RELEASE_SHA" "$REVISION"; then
echo "Error: The codeql version $REVISION is not downstream of the query-pack version $PREVIOUS_RELEASE_SHA"
exit 1
fi
# Get the version of the codeql code specified by the codeml-automodel release
git checkout "$REVISION"
fi
# Get the absolute path of the automodel repo
AUTOMODEL_ROOT="$(readlink -f "$(dirname $0)")"
# Get the absolute path of the workspace root
WORKSPACE_ROOT="$AUTOMODEL_ROOT/../../.."
# Specify the groups of queries to test and publish
GRPS="automodel,-test"
# Install the codeql gh extension
gh extensions install github/gh-codeql
pushd "$AUTOMODEL_ROOT"
echo Testing automodel queries
gh codeql test run test
popd
pushd "$WORKSPACE_ROOT"
echo "Preparing the release"
gh codeql pack release --groups $GRPS -v
if [ $DRY_RUN = 1 ]; then
echo "Dry run: not publishing the query pack"
gh codeql pack publish --groups $GRPS --dry-run -v
else
echo "Not a dry run! Publishing the query pack"
gh codeql pack publish --groups $GRPS -v
fi
echo "Bumping versions"
gh codeql pack post-release --groups $GRPS -v
popd
# The above commands update
# ./src/CHANGELOG.md
# ./src/codeql-pack.release.yml
# ./src/qlpack.yml
# and add a new file
# ./src/change-notes/released/<version>.md
# Get the filename of the most recently created file in ./src/change-notes/released/*.md
# This will be the file for the new release
NEW_CHANGE_NOTES_FILE=$(ls -t ./src/change-notes/released/*.md | head -n 1)
# Make a copy of the modified files
mv ./src/CHANGELOG.md ./src/CHANGELOG.md.dry-run
mv ./src/codeql-pack.release.yml ./src/codeql-pack.release.yml.dry-run
mv ./src/qlpack.yml ./src/qlpack.yml.dry-run
mv "$NEW_CHANGE_NOTES_FILE" ./src/change-notes/released.md.dry-run
if [ $OVERRIDE_RELEASE = 1 ]; then
# Restore the original files
git checkout ./src/CHANGELOG.md
git checkout ./src/codeql-pack.release.yml
git checkout ./src/qlpack.yml
else
# Restore the original files
git checkout "$CURRENT_BRANCH" --force
fi
if [ $DRY_RUN = 1 ]; then
echo "Inspect the updated dry-run version files:"
ls -l ./src/*.dry-run
ls -l ./src/change-notes/*.dry-run
else
# Add the updated files to the current branch
echo "Adding the version changes"
mv -f ./src/CHANGELOG.md.dry-run ./src/CHANGELOG.md
mv -f ./src/codeql-pack.release.yml.dry-run ./src/codeql-pack.release.yml
mv -f ./src/qlpack.yml.dry-run ./src/qlpack.yml
mv -f ./src/change-notes/released.md.dry-run "$NEW_CHANGE_NOTES_FILE"
git add ./src/CHANGELOG.md
git add ./src/codeql-pack.release.yml
git add ./src/qlpack.yml
git add "$NEW_CHANGE_NOTES_FILE"
echo "Added the following updated version files to the current branch:"
git status -s
echo "To complete the release, please commit these files and merge to the main branch"
fi
echo "Done"

View File

@@ -1,183 +0,0 @@
private import java
private import semmle.code.java.dataflow.ExternalFlow as ExternalFlow
private import semmle.code.java.dataflow.TaintTracking
private import semmle.code.java.security.RequestForgeryConfig
private import semmle.code.java.security.CommandLineQuery
private import semmle.code.java.security.SqlConcatenatedQuery
private import semmle.code.java.security.SqlInjectionQuery
private import semmle.code.java.security.UrlRedirectQuery
private import semmle.code.java.security.TaintedPathQuery
private import semmle.code.java.security.SqlInjectionQuery
private import AutomodelJavaUtil
private newtype TSinkModel =
MkSinkModel(
string package, string type, boolean subtypes, string name, string signature, string ext,
string input, string kind, string provenance
) {
ExternalFlow::sinkModel(package, type, subtypes, name, signature, ext, input, kind, provenance,
_)
}
class SinkModel extends TSinkModel {
string package;
string type;
boolean subtypes;
string name;
string signature;
string ext;
string input;
string kind;
string provenance;
SinkModel() {
this = MkSinkModel(package, type, subtypes, name, signature, ext, input, kind, provenance)
}
/** Gets the package for this sink model. */
string getPackage() { result = package }
/** Gets the type for this sink model. */
string getType() { result = type }
/** Gets whether this sink model considers subtypes. */
boolean getSubtypes() { result = subtypes }
/** Gets the name for this sink model. */
string getName() { result = name }
/** Gets the signature for this sink model. */
string getSignature() { result = signature }
/** Gets the input for this sink model. */
string getInput() { result = input }
/** Gets the extension for this sink model. */
string getExt() { result = ext }
/** Gets the kind for this sink model. */
string getKind() { result = kind }
/** Gets the provenance for this sink model. */
string getProvenance() { result = provenance }
/** Gets the number of instances of this sink model. */
int getInstanceCount() { result = count(PotentialSinkModelExpr p | p.getSinkModel() = this) }
/** Gets a string representation of this sink model. */
string toString() {
result =
"SinkModel(" + package + ", " + type + ", " + subtypes + ", " + name + ", " + signature + ", "
+ ext + ", " + input + ", " + kind + ", " + provenance + ")"
}
/** Gets a string representation of this sink model as it would appear in a Models-as-Data file. */
string getRepr() {
result =
"\"" + package + "\", \"" + type + "\", " + pyBool(subtypes) + ", \"" + name + "\", \"" +
signature + "\", \"" + ext + "\", \"" + input + "\", \"" + kind + "\", \"" + provenance +
"\""
}
}
/** An expression that may correspond to a sink model. */
class PotentialSinkModelExpr extends Expr {
/**
* Holds if this expression has the given signature. The signature should contain enough
* information to determine a corresponding sink model, if one exists.
*/
pragma[nomagic]
predicate hasSignature(
string package, string type, boolean subtypes, string name, string signature, string input
) {
exists(Call call, Callable callable, int argIdx |
call.getCallee().getSourceDeclaration() = callable and
(
this = call.getArgument(argIdx)
or
this = call.getQualifier() and argIdx = -1
) and
(if argIdx = -1 then input = "Argument[this]" else input = "Argument[" + argIdx + "]") and
package = callable.getDeclaringType().getPackage().getName() and
type = callable.getDeclaringType().getErasure().(RefType).getNestedName() and
subtypes = considerSubtypes(callable) and
name = callable.getName() and
signature = ExternalFlow::paramsString(callable)
)
}
/** Gets a sink model that corresponds to this expression. */
SinkModel getSinkModel() {
this.hasSignature(result.getPackage(), result.getType(), result.getSubtypes(), result.getName(),
result.getSignature(), result.getInput())
}
}
private string pyBool(boolean b) {
b = true and result = "True"
or
b = false and result = "False"
}
/**
* Gets a string representation of the existing sink model at the expression `e`, in the format in
* which it would appear in a Models-as-Data file. Also restricts the provenance of the sink model
* to be `ai-generated`.
*/
string getSinkModelRepr(PotentialSinkModelExpr e) {
result = e.getSinkModel().getRepr() and
e.getSinkModel().getProvenance() = "ai-generated"
}
/**
* Gets the string representation of a sink model in a format suitable for appending to an alert
* message.
*/
string getSinkModelQueryRepr(PotentialSinkModelExpr e) {
result = "\nsinkModel: " + getSinkModelRepr(e)
}
/**
* A parameterised module that takes a dataflow config, and exposes a predicate for counting the
* number of AI-generated sink models that appear in alerts for that query.
*/
private module SinkTallier<DataFlow::ConfigSig Config> {
module ConfigFlow = TaintTracking::Global<Config>;
predicate getSinkModelCount(int c, SinkModel s) {
s = any(ConfigFlow::PathNode sink).getNode().asExpr().(PotentialSinkModelExpr).getSinkModel() and
c =
strictcount(ConfigFlow::PathNode sink |
ConfigFlow::flowPath(_, sink) and
s = sink.getNode().asExpr().(PotentialSinkModelExpr).getSinkModel()
)
}
}
predicate sinkModelTallyPerQuery(string queryName, int alertCount, SinkModel sinkModel) {
queryName = "java/request-forgery" and
SinkTallier<RequestForgeryConfig>::getSinkModelCount(alertCount, sinkModel)
or
queryName = "java/command-line-injection" and
SinkTallier<InputToArgumentToExecFlowConfig>::getSinkModelCount(alertCount, sinkModel)
or
queryName = "java/concatenated-sql-query" and
SinkTallier<UncontrolledStringBuilderSourceFlowConfig>::getSinkModelCount(alertCount, sinkModel)
or
queryName = "java/ssrf" and
SinkTallier<RequestForgeryConfig>::getSinkModelCount(alertCount, sinkModel)
or
queryName = "java/path-injection" and
SinkTallier<TaintedPathConfig>::getSinkModelCount(alertCount, sinkModel)
or
queryName = "java/unvalidated-url-redirection" and
SinkTallier<UrlRedirectConfig>::getSinkModelCount(alertCount, sinkModel)
or
queryName = "java/sql-injection" and
SinkTallier<QueryInjectionFlowConfig>::getSinkModelCount(alertCount, sinkModel)
}
predicate sinkModelTally(int alertCount, SinkModel sinkModel) {
sinkModelTallyPerQuery(_, _, sinkModel) and
alertCount = sum(int c | sinkModelTallyPerQuery(_, c, sinkModel))
}

View File

@@ -1,16 +0,0 @@
/**
* @name Number of alerts per sink model
* @description Counts the number of alerts using `ai-generated` sink models.
* @kind table
* @id java/ml/metrics-count-alerts-per-sink-model
* @tags internal automodel metrics
*/
private import java
private import AutomodelAlertSinkUtil
from int alertCount, SinkModel s
where sinkModelTally(alertCount, s) and s.getProvenance() = "ai-generated"
select alertCount, s.getPackage() as package, s.getType() as type, s.getSubtypes() as subtypes,
s.getName() as name, s.getSignature() as signature, s.getInput() as input, s.getExt() as ext,
s.getKind() as kind, s.getProvenance() as provenance order by alertCount desc

View File

@@ -1,19 +0,0 @@
/**
* @name Number of alerts per sink model and query
* @description Counts the number of alerts per query using `ai-generated` sink models.
* @kind table
* @id java/ml/metrics-count-alerts-per-sink-model-and-query
* @tags internal automodel metrics
*/
private import java
private import AutomodelAlertSinkUtil
from string queryId, int alertCount, SinkModel s
where
sinkModelTallyPerQuery(queryId, alertCount, s) and
s.getProvenance() = "ai-generated"
select queryId, alertCount, s.getPackage() as package, s.getType() as type,
s.getSubtypes() as subtypes, s.getName() as name, s.getSignature() as signature,
s.getInput() as input, s.getExt() as ext, s.getKind() as kind, s.getProvenance() as provenance
order by queryId, alertCount desc

View File

@@ -1,677 +0,0 @@
/**
* For internal use only.
*/
private import java
private import semmle.code.Location as Location
private import semmle.code.java.dataflow.DataFlow
private import semmle.code.java.dataflow.TaintTracking
private import semmle.code.java.dataflow.ExternalFlow as ExternalFlow
private import semmle.code.java.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
private import semmle.code.java.security.ExternalAPIs as ExternalAPIs
private import semmle.code.java.Expr as Expr
private import semmle.code.java.security.QueryInjection
private import semmle.code.java.dataflow.internal.ModelExclusions as ModelExclusions
private import AutomodelJavaUtil as AutomodelJavaUtil
private import semmle.code.java.security.PathSanitizer as PathSanitizer
import AutomodelSharedCharacteristics as SharedCharacteristics
import AutomodelEndpointTypes as AutomodelEndpointTypes
newtype JavaRelatedLocationType =
CallContext() or
MethodDoc() or
ClassDoc()
newtype TApplicationModeEndpoint =
TExplicitArgument(Call call, DataFlow::Node arg) {
AutomodelJavaUtil::isFromSource(call) and
exists(Argument argExpr |
arg.asExpr() = argExpr and call = argExpr.getCall() and not argExpr.isVararg()
) and
not AutomodelJavaUtil::isUnexploitableType(arg.getType())
} or
TInstanceArgument(Call call, DataFlow::Node arg) {
AutomodelJavaUtil::isFromSource(call) and
arg = DataFlow::getInstanceArgument(call) and
not call instanceof ConstructorCall and
not AutomodelJavaUtil::isUnexploitableType(arg.getType())
} or
TImplicitVarargsArray(Call call, DataFlow::ImplicitVarargsArray arg, int idx) {
AutomodelJavaUtil::isFromSource(call) and
call = arg.getCall() and
idx = call.getCallee().getVaragsParameterIndex() and
not AutomodelJavaUtil::isUnexploitableType(arg.getType())
} or
TMethodReturnValue(MethodCall call) {
AutomodelJavaUtil::isFromSource(call) and
not AutomodelJavaUtil::isUnexploitableType(call.getType())
} or
TOverriddenParameter(Parameter p, Method overriddenMethod) {
AutomodelJavaUtil::isFromSource(p) and
p.getCallable().(Method).overrides(overriddenMethod)
}
/**
* An endpoint is a node that is a candidate for modeling.
*/
abstract private class ApplicationModeEndpoint extends TApplicationModeEndpoint {
/**
* Gets the callable to be modeled that this endpoint represents.
*/
abstract Callable getCallable();
/**
* Gets the input (if any) for this endpoint, eg.: `Argument[0]`.
*
* For endpoints that are source candidates, this will be `none()`.
*/
abstract string getMaDInput();
/**
* Gets the output (if any) for this endpoint, eg.: `ReturnValue`.
*
* For endpoints that are sink candidates, this will be `none()`.
*/
abstract string getMaDOutput();
abstract Top asTop();
/**
* Converts the endpoint to a node that can be used in a data flow graph.
*/
abstract DataFlow::Node asNode();
string getExtensibleType() {
if not exists(this.getMaDInput()) and exists(this.getMaDOutput())
then result = "sourceModel"
else
if exists(this.getMaDInput()) and not exists(this.getMaDOutput())
then result = "sinkModel"
else none() // if both exist, it would be a summaryModel (not yet supported)
}
abstract string toString();
}
class TCallArgument = TExplicitArgument or TInstanceArgument or TImplicitVarargsArray;
/**
* An endpoint that represents an "argument" to a call in a broad sense, including
* both explicit arguments and the instance argument.
*/
abstract class CallArgument extends ApplicationModeEndpoint, TCallArgument {
Call call;
DataFlow::Node arg;
override Callable getCallable() { result = call.getCallee().getSourceDeclaration() }
override string getMaDOutput() { none() }
override DataFlow::Node asNode() { result = arg }
Call getCall() { result = call }
override string toString() { result = arg.toString() }
}
/**
* An endpoint that represents an explicit argument to a call.
*/
class ExplicitArgument extends CallArgument, TExplicitArgument {
ExplicitArgument() { this = TExplicitArgument(call, arg) }
private int getArgIndex() { this.asTop() = call.getArgument(result) }
override string getMaDInput() { result = "Argument[" + this.getArgIndex() + "]" }
override Top asTop() { result = arg.asExpr() }
}
/**
* An endpoint that represents the instance argument to a call.
*/
class InstanceArgument extends CallArgument, TInstanceArgument {
InstanceArgument() { this = TInstanceArgument(call, arg) }
override string getMaDInput() { result = "Argument[this]" }
override Top asTop() { if exists(arg.asExpr()) then result = arg.asExpr() else result = call }
override string toString() { result = arg.toString() }
}
/**
* An endpoint that represents an implicit varargs array.
* We choose to represent the varargs array as a single endpoint, rather than as multiple endpoints.
*
* This avoids the problem of having to deal with redundant endpoints downstream.
*
* In order to be able to distinguish between varargs endpoints and regular endpoints, we export the `isVarargsArray`
* meta data field in the extraction queries.
*/
class ImplicitVarargsArray extends CallArgument, TImplicitVarargsArray {
int idx;
ImplicitVarargsArray() { this = TImplicitVarargsArray(call, arg, idx) }
override string getMaDInput() { result = "Argument[" + idx + "]" }
override Top asTop() { result = call }
}
/**
* An endpoint that represents a method call. The `ReturnValue` of a method call
* may be a source.
*/
class MethodReturnValue extends ApplicationModeEndpoint, TMethodReturnValue {
MethodCall call;
MethodReturnValue() { this = TMethodReturnValue(call) }
override Callable getCallable() { result = call.getCallee().getSourceDeclaration() }
override string getMaDInput() { none() }
override string getMaDOutput() { result = "ReturnValue" }
override Top asTop() { result = call }
override DataFlow::Node asNode() { result.asExpr() = call }
override string toString() { result = call.toString() }
}
/**
* An endpoint that represents a parameter of an overridden method that may be
* a source.
*/
class OverriddenParameter extends ApplicationModeEndpoint, TOverriddenParameter {
Parameter p;
Method overriddenMethod;
OverriddenParameter() { this = TOverriddenParameter(p, overriddenMethod) }
override Callable getCallable() {
// NB: we're returning the overridden callable here. This means that the
// candidate model will be about the overridden method, not the overriding
// method. This is a more general model, that also applies to other
// subclasses of the overridden class.
result = overriddenMethod.getSourceDeclaration()
}
private int getArgIndex() { p.getCallable().getParameter(result) = p }
override string getMaDInput() { none() }
override string getMaDOutput() { result = "Parameter[" + this.getArgIndex() + "]" }
override Top asTop() { result = p }
override DataFlow::Node asNode() { result.(DataFlow::ParameterNode).asParameter() = p }
override string toString() { result = p.toString() }
}
/**
* A candidates implementation.
*
* Some important notes:
* - This mode is using arguments as endpoints.
* - We use the `CallContext` (the surrounding call expression) as related location.
*/
module ApplicationCandidatesImpl implements SharedCharacteristics::CandidateSig {
// for documentation of the implementations here, see the QLDoc in the CandidateSig signature module.
class Endpoint = ApplicationModeEndpoint;
class EndpointType = AutomodelEndpointTypes::EndpointType;
class SinkType = AutomodelEndpointTypes::SinkType;
class SourceType = AutomodelEndpointTypes::SourceType;
class RelatedLocation = Location::Top;
class RelatedLocationType = JavaRelatedLocationType;
// Sanitizers are currently not modeled in MaD. TODO: check if this has large negative impact.
predicate isSanitizer(Endpoint e, EndpointType t) {
exists(t) and
AutomodelJavaUtil::isUnexploitableType([
// for most endpoints, we can get the type from the node
e.asNode().getType(),
// but not for calls to void methods, where we need to go via the AST
e.asTop().(Expr).getType()
])
or
t instanceof AutomodelEndpointTypes::PathInjectionSinkType and
e.asNode() instanceof PathSanitizer::PathInjectionSanitizer
}
RelatedLocation asLocation(Endpoint e) { result = e.asTop() }
predicate isKnownKind = AutomodelJavaUtil::isKnownKind/2;
predicate isSink(Endpoint e, string kind, string provenance) {
exists(
string package, string type, boolean subtypes, string name, string signature, string ext,
string input
|
sinkSpec(e, package, type, subtypes, name, signature, ext, input) and
ExternalFlow::sinkModel(package, type, subtypes, name, [signature, ""], ext, input, kind,
provenance, _)
)
or
isCustomSink(e, kind) and provenance = "custom-sink"
}
predicate isSource(Endpoint e, string kind, string provenance) {
exists(
string package, string type, boolean subtypes, string name, string signature, string ext,
string output
|
sourceSpec(e, package, type, subtypes, name, signature, ext, output) and
ExternalFlow::sourceModel(package, type, subtypes, name, [signature, ""], ext, output, kind,
provenance, _)
)
}
predicate isNeutral(Endpoint e) {
exists(string package, string type, string name, string signature, string endpointType |
sinkSpec(e, package, type, _, name, signature, _, _) and
endpointType = "sink"
or
sourceSpec(e, package, type, _, name, signature, _, _) and
endpointType = "source"
|
ExternalFlow::neutralModel(package, type, name, [signature, ""], endpointType, _)
)
}
/**
* Holds if the endpoint concerns a callable with the given package, type, name and signature.
*
* If `subtypes` is `false`, only the exact callable is considered. If `true`, the callable and
* all its overrides are considered.
*/
additional predicate endpointCallable(
Endpoint e, string package, string type, boolean subtypes, string name, string signature
) {
exists(Callable c |
c = e.getCallable() and subtypes in [true, false]
or
e.getCallable().(Method).getSourceDeclaration().overrides+(c) and subtypes = true
|
c.hasQualifiedName(package, type, name) and
signature = ExternalFlow::paramsString(c)
)
}
additional predicate sinkSpec(
Endpoint e, string package, string type, boolean subtypes, string name, string signature,
string ext, string input
) {
endpointCallable(e, package, type, subtypes, name, signature) and
ext = "" and
input = e.getMaDInput()
}
additional predicate sourceSpec(
Endpoint e, string package, string type, boolean subtypes, string name, string signature,
string ext, string output
) {
endpointCallable(e, package, type, subtypes, name, signature) and
ext = "" and
output = e.getMaDOutput()
}
/**
* Gets the related location for the given endpoint.
*
* The only related location we model is the the call expression surrounding to
* which the endpoint is either argument or qualifier (known as the call context).
*/
RelatedLocation getRelatedLocation(Endpoint e, RelatedLocationType type) {
type = CallContext() and
result = e.(CallArgument).getCall()
or
type = MethodDoc() and
result = e.getCallable().(Documentable).getJavadoc()
or
type = ClassDoc() and
result = e.getCallable().getDeclaringType().(Documentable).getJavadoc()
}
}
/**
* Contains endpoints that are defined in QL code rather than as a MaD model. Ideally this predicate
* should be empty.
*/
private predicate isCustomSink(Endpoint e, string kind) {
e.asNode() instanceof QueryInjectionSink and kind = "sql"
}
module CharacteristicsImpl =
SharedCharacteristics::SharedCharacteristics<ApplicationCandidatesImpl>;
class EndpointCharacteristic = CharacteristicsImpl::EndpointCharacteristic;
class Endpoint = ApplicationCandidatesImpl::Endpoint;
/*
* Predicates that are used to surface prompt examples and candidates for classification with an ML model.
*/
/**
* A MetadataExtractor that extracts metadata for application mode.
*/
class ApplicationModeMetadataExtractor extends string {
ApplicationModeMetadataExtractor() { this = "ApplicationModeMetadataExtractor" }
predicate hasMetadata(
Endpoint e, string package, string type, string subtypes, string name, string signature,
string input, string output, string isVarargsArray, string alreadyAiModeled,
string extensibleType
) {
exists(Callable callable | e.getCallable() = callable |
(if exists(e.getMaDInput()) then input = e.getMaDInput() else input = "") and
(if exists(e.getMaDOutput()) then output = e.getMaDOutput() else output = "") and
package = callable.getDeclaringType().getPackage().getName() and
// we're using the erased types because the MaD convention is to not specify type parameters.
// Whether something is or isn't a sink doesn't usually depend on the type parameters.
type = callable.getDeclaringType().getErasure().(RefType).getNestedName() and
subtypes = AutomodelJavaUtil::considerSubtypes(callable).toString() and
name = callable.getName() and
signature = ExternalFlow::paramsString(callable) and
(
if e instanceof ImplicitVarargsArray
then isVarargsArray = "true"
else isVarargsArray = "false"
) and
extensibleType = e.getExtensibleType()
) and
(
not CharacteristicsImpl::isModeled(e, _, extensibleType, _) and alreadyAiModeled = ""
or
CharacteristicsImpl::isModeled(e, _, extensibleType, alreadyAiModeled)
)
}
}
/**
* Holds if the given `endpoint` should be considered a candidate for the `extensibleType`.
*
* The other parameters record various other properties of interest.
*/
predicate isCandidate(
Endpoint endpoint, string package, string type, string subtypes, string name, string signature,
string input, string output, string isVarargs, string extensibleType, string alreadyAiModeled
) {
CharacteristicsImpl::isCandidate(endpoint, _) and
not exists(CharacteristicsImpl::UninterestingToModelCharacteristic u |
u.appliesToEndpoint(endpoint)
) and
any(ApplicationModeMetadataExtractor meta)
.hasMetadata(endpoint, package, type, subtypes, name, signature, input, output, isVarargs,
alreadyAiModeled, extensibleType) and
// If a node is already modeled in MaD, we don't include it as a candidate. Otherwise, we might include it as a
// candidate for query A, but the model will label it as a sink for one of the sink types of query B, for which it's
// already a known sink. This would result in overlap between our detected sinks and the pre-existing modeling. We
// assume that, if a sink has already been modeled in a MaD model, then it doesn't belong to any additional sink
// types, and we don't need to reexamine it.
alreadyAiModeled.matches(["", "%ai-%"]) and
AutomodelJavaUtil::includeAutomodelCandidate(package, type, name, signature)
}
/**
* Holds if the given `endpoint` is a negative example for the `extensibleType`
* because of the `characteristic`.
*
* The other parameters record various other properties of interest.
*/
predicate isNegativeExample(
Endpoint endpoint, EndpointCharacteristic characteristic, float confidence, string package,
string type, string subtypes, string name, string signature, string input, string output,
string isVarargsArray, string extensibleType
) {
characteristic.appliesToEndpoint(endpoint) and
// the node is known not to be an endpoint of any appropriate type
forall(AutomodelEndpointTypes::EndpointType tp |
tp = CharacteristicsImpl::getAPotentialType(endpoint)
|
characteristic.hasImplications(tp, false, _)
) and
// the lowest confidence across all endpoint types should be at least highConfidence
confidence =
min(float c |
characteristic.hasImplications(CharacteristicsImpl::getAPotentialType(endpoint), false, c)
) and
confidence >= SharedCharacteristics::highConfidence() and
any(ApplicationModeMetadataExtractor meta)
.hasMetadata(endpoint, package, type, subtypes, name, signature, input, output,
isVarargsArray, _, extensibleType) and
// It's valid for a node to be both a potential source/sanitizer and a sink. We don't want to include such nodes
// as negative examples in the prompt, because they're ambiguous and might confuse the model, so we explicitly exclude them here.
not exists(EndpointCharacteristic characteristic2, float confidence2 |
characteristic2 != characteristic
|
characteristic2.appliesToEndpoint(endpoint) and
confidence2 >= SharedCharacteristics::maximalConfidence() and
characteristic2
.hasImplications(CharacteristicsImpl::getAPotentialType(endpoint), true, confidence2)
)
}
/**
* Holds if the given `endpoint` is a positive example for the `endpointType`.
*
* The other parameters record various other properties of interest.
*/
predicate isPositiveExample(
Endpoint endpoint, string endpointType, string package, string type, string subtypes, string name,
string signature, string input, string output, string isVarargsArray, string extensibleType
) {
any(ApplicationModeMetadataExtractor meta)
.hasMetadata(endpoint, package, type, subtypes, name, signature, input, output,
isVarargsArray, _, extensibleType) and
CharacteristicsImpl::isKnownAs(endpoint, endpointType, _) and
exists(CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, CallContext()))
}
/*
* EndpointCharacteristic classes that are specific to Automodel for Java.
*/
/**
* A negative characteristic that indicates that parameters of an is-style boolean method should not be considered sinks.
*
* A sink is highly unlikely to be exploitable if its callable's name starts with `is` and the callable has a boolean return
* type (e.g. `isDirectory`). These kinds of calls normally do only checks, and appear before the proper call that does
* the dangerous/interesting thing, so we want the latter to be modeled as the sink.
*
* TODO: this might filter too much, it's possible that methods with more than one parameter contain interesting sinks
*/
private class UnexploitableIsCharacteristic extends CharacteristicsImpl::NotASinkCharacteristic {
UnexploitableIsCharacteristic() { this = "argument of is-style boolean method" }
override predicate appliesToEndpoint(Endpoint e) {
e.getCallable().getName().matches("is%") and
e.getCallable().getReturnType() instanceof BooleanType and
not ApplicationCandidatesImpl::isSink(e, _, _)
}
}
/**
* A negative characteristic that indicates that parameters of an existence-checking boolean method should not be
* considered sinks.
*
* A sink is highly unlikely to be exploitable if its callable's name is `exists` or `notExists` and the callable has a
* boolean return type. These kinds of calls normally do only checks, and appear before the proper call that does the
* dangerous/interesting thing, so we want the latter to be modeled as the sink.
*/
private class UnexploitableExistsCharacteristic extends CharacteristicsImpl::NotASinkCharacteristic {
UnexploitableExistsCharacteristic() { this = "argument of existence-checking boolean method" }
override predicate appliesToEndpoint(Endpoint e) {
exists(Callable callable | callable = e.getCallable() |
callable.getName().toLowerCase() = ["exists", "notexists"] and
callable.getReturnType() instanceof BooleanType
)
}
}
/**
* A negative characteristic that indicates that parameters of an exception method or constructor should not be considered sinks,
* and its return value should not be considered a source.
*/
private class ExceptionCharacteristic extends CharacteristicsImpl::NeitherSourceNorSinkCharacteristic
{
ExceptionCharacteristic() { this = "argument/result of exception-related method" }
override predicate appliesToEndpoint(Endpoint e) {
e.getCallable().getDeclaringType().getASupertype*() instanceof TypeThrowable and
(
e.getExtensibleType() = "sinkModel" and
not ApplicationCandidatesImpl::isSink(e, _, _)
or
e.getExtensibleType() = "sourceModel" and
not ApplicationCandidatesImpl::isSource(e, _, _) and
e.getMaDOutput() = "ReturnValue"
)
}
}
/**
* A negative characteristic that indicates that an endpoint is a MaD taint step. MaD modeled taint steps are global,
* so they are not sinks for any query. Non-MaD taint steps might be specific to a particular query, so we don't
* filter those out.
*/
private class IsMaDTaintStepCharacteristic extends CharacteristicsImpl::NotASinkCharacteristic {
IsMaDTaintStepCharacteristic() { this = "taint step" }
override predicate appliesToEndpoint(Endpoint e) {
FlowSummaryImpl::Private::Steps::summaryThroughStepValue(e.asNode(), _, _)
or
FlowSummaryImpl::Private::Steps::summaryThroughStepTaint(e.asNode(), _, _)
or
FlowSummaryImpl::Private::Steps::summaryGetterStep(e.asNode(), _, _, _)
or
FlowSummaryImpl::Private::Steps::summarySetterStep(e.asNode(), _, _, _)
}
}
/**
* A call to a method that's known locally will not be considered as a candidate to model.
*
* The reason is that we would expect data/taint flow into the method implementation to uncover
* any sinks that are present there.
*/
private class LocalCall extends CharacteristicsImpl::UninterestingToModelCharacteristic {
LocalCall() { this = "local call" }
override predicate appliesToEndpoint(Endpoint e) {
e.(CallArgument).getCallable().fromSource()
or
e.(MethodReturnValue).getCallable().fromSource()
}
}
/**
* A characteristic that marks endpoints as uninteresting to model, according to the Java ModelExclusions module.
*/
private class ExcludedFromModeling extends CharacteristicsImpl::UninterestingToModelCharacteristic {
ExcludedFromModeling() { this = "excluded from modeling" }
override predicate appliesToEndpoint(Endpoint e) {
ModelExclusions::isUninterestingForModels(e.getCallable())
}
}
/**
* A negative characteristic that filters out non-public methods. Non-public methods are not interesting to include in
* the standard Java modeling, because they cannot be called from outside the package.
*/
private class NonPublicMethodCharacteristic extends CharacteristicsImpl::UninterestingToModelCharacteristic
{
NonPublicMethodCharacteristic() { this = "non-public method" }
override predicate appliesToEndpoint(Endpoint e) {
exists(Callable c | c = e.getCallable() | not c.isPublic())
}
}
/**
* A negative characteristic that indicates that an endpoint is a non-sink argument to a method whose sinks have already
* been modeled _manually_. This is restricted to manual sinks only, because only during the manual process do we have
* the expectation that all sinks present in a method have been considered.
*
* WARNING: These endpoints should not be used as negative samples for training, because some sinks may have been missed
* when the method was modeled. Specifically, as we start using ATM to merge in new declarations, we can be less sure
* that a method with one argument modeled as a MaD sink has also had its remaining arguments manually reviewed. The
* ML model might have predicted argument 0 of some method to be a sink but not argument 1, when in fact argument 1 is
* also a sink.
*/
private class OtherArgumentToModeledMethodCharacteristic extends CharacteristicsImpl::LikelyNotASinkCharacteristic
{
OtherArgumentToModeledMethodCharacteristic() {
this = "other argument to a method that has already been modeled manually"
}
override predicate appliesToEndpoint(Endpoint e) {
not ApplicationCandidatesImpl::isSink(e, _, _) and
exists(CallArgument otherSink |
ApplicationCandidatesImpl::isSink(otherSink, _, "manual") and
e.(CallArgument).getCall() = otherSink.getCall() and
e != otherSink
)
}
}
/**
* Holds if the type of the given expression is annotated with `@FunctionalInterface`.
*/
predicate hasFunctionalInterfaceType(Expr e) {
exists(RefType tp | tp = e.getType().getErasure() |
tp.getAnAssociatedAnnotation().getType().hasQualifiedName("java.lang", "FunctionalInterface")
)
}
/**
* A characteristic that marks functional expression as likely not sinks.
*
* These expressions may well _contain_ sinks, but rarely are sinks themselves.
*/
private class FunctionValueCharacteristic extends CharacteristicsImpl::LikelyNotASinkCharacteristic {
FunctionValueCharacteristic() { this = "function value" }
override predicate appliesToEndpoint(Endpoint e) {
exists(Expr expr | expr = e.asNode().asExpr() |
expr instanceof FunctionalExpr or hasFunctionalInterfaceType(expr)
)
}
}
/**
* A negative characteristic that indicates that an endpoint is not a `to` node for any known taint step. Such a node
* cannot be tainted, because taint can't flow into it.
*
* WARNING: These endpoints should not be used as negative samples for training, because they may include sinks for
* which our taint tracking modeling is incomplete.
*/
private class CannotBeTaintedCharacteristic extends CharacteristicsImpl::LikelyNotASinkCharacteristic
{
CannotBeTaintedCharacteristic() { this = "cannot be tainted" }
override predicate appliesToEndpoint(Endpoint e) { not this.isKnownOutNodeForStep(e) }
/**
* Holds if the node `n` is known as the predecessor in a modeled flow step.
*/
private predicate isKnownOutNodeForStep(Endpoint e) {
e.asNode().asExpr() instanceof Call or // we just assume flow in that case
TaintTracking::localTaintStep(_, e.asNode()) or
FlowSummaryImpl::Private::Steps::summaryThroughStepValue(_, e.asNode(), _) or
FlowSummaryImpl::Private::Steps::summaryThroughStepTaint(_, e.asNode(), _) or
FlowSummaryImpl::Private::Steps::summaryGetterStep(_, _, e.asNode(), _) or
FlowSummaryImpl::Private::Steps::summarySetterStep(_, _, e.asNode(), _)
}
}

View File

@@ -1,81 +0,0 @@
/**
* Surfaces the endpoints that are not already known to be sinks, and are therefore used as candidates for
* classification with an ML model.
*
* Note: This query does not actually classify the endpoints using the model.
*
* @name Automodel candidates (application mode)
* @description A query to extract automodel candidates in application mode.
* @kind problem
* @problem.severity recommendation
* @id java/ml/extract-automodel-application-candidates
* @tags internal extract automodel application-mode candidates
*/
import java
private import AutomodelApplicationModeCharacteristics
private import AutomodelJavaUtil
/**
* Gets a sample of endpoints (of at most `limit` samples) with the given method signature.
*
* The main purpose of this helper predicate is to avoid selecting too many candidates, as this may
* cause the SARIF file to exceed the maximum size limit.
*/
bindingset[limit]
private Endpoint getSampleForSignature(
int limit, string package, string type, string subtypes, string name, string signature,
string input, string output, string isVarargs, string extensibleType, string alreadyAiModeled
) {
exists(int n, int num_endpoints, ApplicationModeMetadataExtractor meta |
num_endpoints =
count(Endpoint e |
meta.hasMetadata(e, package, type, subtypes, name, signature, input, output, isVarargs,
alreadyAiModeled, extensibleType)
)
|
result =
rank[n](Endpoint e, Location loc |
loc = e.asTop().getLocation() and
meta.hasMetadata(e, package, type, subtypes, name, signature, input, output, isVarargs,
alreadyAiModeled, extensibleType)
|
e
order by
loc.getFile().getAbsolutePath(), loc.getStartLine(), loc.getStartColumn(),
loc.getEndLine(), loc.getEndColumn()
) and
// To avoid selecting samples that are too close together (as the ranking above goes by file
// path first), we select `limit` evenly spaced samples from the ranked list of endpoints. By
// default this would always include the first sample, so we add a random-chosen prime offset
// to the first sample index, and reduce modulo the number of endpoints.
// Finally, we add 1 to the result, as ranking results in a 1-indexed relation.
n = 1 + (([0 .. limit - 1] * (num_endpoints / limit).floor() + 46337) % num_endpoints)
)
}
from
Endpoint endpoint, DollarAtString package, DollarAtString type, DollarAtString subtypes,
DollarAtString name, DollarAtString signature, DollarAtString input, DollarAtString output,
DollarAtString isVarargsArray, DollarAtString alreadyAiModeled, DollarAtString extensibleType
where
isCandidate(endpoint, package, type, subtypes, name, signature, input, output, isVarargsArray,
extensibleType, alreadyAiModeled) and
endpoint =
getSampleForSignature(9, package, type, subtypes, name, signature, input, output,
isVarargsArray, extensibleType, alreadyAiModeled)
select endpoint.asNode(),
"Related locations: $@, $@, $@." + "\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@.", //
CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, CallContext()), "CallContext", //
CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, MethodDoc()), "MethodDoc", //
CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, ClassDoc()), "ClassDoc", //
package, "package", //
type, "type", //
subtypes, "subtypes", //
name, "name", // method name
signature, "signature", //
input, "input", //
output, "output", //
isVarargsArray, "isVarargsArray", //
alreadyAiModeled, "alreadyAiModeled", //
extensibleType, "extensibleType"

View File

@@ -1,66 +0,0 @@
/**
* Surfaces endpoints that are non-sinks with high confidence, for use as negative examples in the prompt.
*
* @name Negative examples (application mode)
* @kind problem
* @problem.severity recommendation
* @id java/ml/extract-automodel-application-negative-examples
* @tags internal extract automodel application-mode negative examples
*/
private import java
private import AutomodelApplicationModeCharacteristics
private import AutomodelEndpointTypes
private import AutomodelJavaUtil
/**
* Gets a sample of endpoints (of at most `limit` samples) for which the given characteristic applies.
*
* The main purpose of this helper predicate is to avoid selecting too many samples, as this may
* cause the SARIF file to exceed the maximum size limit.
*/
bindingset[limit]
Endpoint getSampleForCharacteristic(EndpointCharacteristic c, int limit) {
exists(int n, int num_endpoints | num_endpoints = count(Endpoint e | c.appliesToEndpoint(e)) |
result =
rank[n](Endpoint e, Location loc |
loc = e.asTop().getLocation() and c.appliesToEndpoint(e)
|
e
order by
loc.getFile().getAbsolutePath(), loc.getStartLine(), loc.getStartColumn(),
loc.getEndLine(), loc.getEndColumn()
) and
// To avoid selecting samples that are too close together (as the ranking above goes by file
// path first), we select `limit` evenly spaced samples from the ranked list of endpoints. By
// default this would always include the first sample, so we add a random-chosen prime offset
// to the first sample index, and reduce modulo the number of endpoints.
// Finally, we add 1 to the result, as ranking results in a 1-indexed relation.
n = 1 + (([0 .. limit - 1] * (num_endpoints / limit).floor() + 46337) % num_endpoints)
)
}
from
Endpoint endpoint, EndpointCharacteristic characteristic, float confidence, string message,
DollarAtString package, DollarAtString type, DollarAtString subtypes, DollarAtString name,
DollarAtString signature, DollarAtString input, DollarAtString output,
DollarAtString isVarargsArray, DollarAtString extensibleType
where
endpoint = getSampleForCharacteristic(characteristic, 100) and
isNegativeExample(endpoint, characteristic, confidence, package, type, subtypes, name, signature,
input, output, isVarargsArray, extensibleType) and
message = characteristic
select endpoint.asNode(),
message + "\nrelated locations: $@, $@, $@." + "\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@.", //
CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, CallContext()), "CallContext", //
CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, MethodDoc()), "MethodDoc", //
CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, ClassDoc()), "ClassDoc", //
package, "package", //
type, "type", //
subtypes, "subtypes", //
name, "name", //
signature, "signature", //
input, "input", //
output, "output", //
isVarargsArray, "isVarargsArray", //
extensibleType, "extensibleType"

View File

@@ -1,37 +0,0 @@
/**
* Surfaces endpoints that are sinks with high confidence, for use as positive examples in the prompt.
*
* @name Positive examples (application mode)
* @kind problem
* @problem.severity recommendation
* @id java/ml/extract-automodel-application-positive-examples
* @tags internal extract automodel application-mode positive examples
*/
private import AutomodelApplicationModeCharacteristics
private import AutomodelEndpointTypes
private import AutomodelJavaUtil
from
Endpoint endpoint, EndpointType endpointType, ApplicationModeMetadataExtractor meta,
DollarAtString package, DollarAtString type, DollarAtString subtypes, DollarAtString name,
DollarAtString signature, DollarAtString input, DollarAtString output,
DollarAtString isVarargsArray, DollarAtString extensibleType
where
isPositiveExample(endpoint, endpointType, package, type, subtypes, name, signature, input, output,
isVarargsArray, extensibleType)
select endpoint.asNode(),
endpointType + "\nrelated locations: $@, $@, $@." +
"\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@.", //
CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, CallContext()), "CallContext", //
CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, MethodDoc()), "MethodDoc", //
CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, ClassDoc()), "ClassDoc", //
package, "package", //
type, "type", //
subtypes, "subtypes", //
name, "name", //
signature, "signature", //
input, "input", //
output, "output", //
isVarargsArray, "isVarargsArray", //
extensibleType, "extensibleType"

View File

@@ -1,5 +0,0 @@
extensions:
- addsTo:
pack: codeql/java-automodel-queries
extensible: automodelCandidateFilter
data: []

View File

@@ -1,19 +0,0 @@
/**
* @name Number of instances of each sink model
* @description Counts the number of instances of `ai-generated` sink models.
* @kind table
* @id java/ml/metrics-count-instances-per-sink-model
* @tags internal automodel metrics
*/
private import java
private import AutomodelAlertSinkUtil
from int instanceCount, SinkModel s
where
instanceCount = s.getInstanceCount() and
instanceCount > 0 and
s.getProvenance() = "ai-generated"
select instanceCount, s.getPackage() as package, s.getType() as type, s.getSubtypes() as subtypes,
s.getName() as name, s.getSignature() as signature, s.getInput() as input, s.getExt() as ext,
s.getKind() as kind, s.getProvenance() as provenance order by instanceCount desc

View File

@@ -1,82 +0,0 @@
/**
* For internal use only.
*
* Defines the set of classes that endpoint scoring models can predict. Endpoint scoring models must
* only predict classes defined within this file. This file is the source of truth for the integer
* representation of each of these classes.
*/
/** A class that can be predicted by a classifier. */
abstract class EndpointType extends string {
/**
* Holds when the string matches the name of the sink / source type.
*/
bindingset[this]
EndpointType() { any() }
/**
* Gets the name of the sink/source kind for this endpoint type as used in models-as-data.
*
* See https://github.com/github/codeql/blob/44213f0144fdd54bb679ca48d68b28dcf820f7a8/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll#LL353C11-L357C31
* for sink types, and https://github.com/github/codeql/blob/44213f0144fdd54bb679ca48d68b28dcf820f7a8/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll#L365
* for source types.
*/
final string getKind() { result = this }
}
/** A class for sink types that can be predicted by a classifier. */
abstract class SinkType extends EndpointType {
bindingset[this]
SinkType() { any() }
}
/** A sink relevant to the SQL injection query */
class SqlInjectionSinkType extends SinkType {
SqlInjectionSinkType() { this = "sql-injection" }
}
/** A sink relevant to the tainted path injection query. */
class PathInjectionSinkType extends SinkType {
PathInjectionSinkType() { this = "path-injection" }
}
/** A sink relevant to the SSRF query. */
class RequestForgerySinkType extends SinkType {
RequestForgerySinkType() { this = "request-forgery" }
}
/** A sink relevant to the command injection query. */
class CommandInjectionSinkType extends SinkType {
CommandInjectionSinkType() { this = "command-injection" }
}
/** A sink relevant to file storage. */
class FileContentStoreSinkType extends SinkType {
FileContentStoreSinkType() { this = "file-content-store" }
}
/** A sink relevant to HTML injection. */
class HtmlInjectionSinkType extends SinkType {
HtmlInjectionSinkType() { this = "html-injection" }
}
/** A sink relevant to LDAP injection. */
class LdapInjectionSinkType extends SinkType {
LdapInjectionSinkType() { this = "ldap-injection" }
}
/** A sink relevant to URL redirection. */
class UrlRedirectionSinkType extends SinkType {
UrlRedirectionSinkType() { this = "url-redirection" }
}
/** A class for source types that can be predicted by a classifier. */
abstract class SourceType extends EndpointType {
bindingset[this]
SourceType() { any() }
}
/** A source of remote data. */
class RemoteSourceType extends SourceType {
RemoteSourceType() { this = "remote" }
}

View File

@@ -1,507 +0,0 @@
/**
* For internal use only.
*/
private import java
private import semmle.code.Location as Location
private import semmle.code.java.dataflow.DataFlow
private import semmle.code.java.dataflow.TaintTracking
private import semmle.code.java.dataflow.ExternalFlow as ExternalFlow
private import semmle.code.java.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
private import semmle.code.java.security.ExternalAPIs as ExternalAPIs
private import semmle.code.java.Expr as Expr
private import semmle.code.java.security.QueryInjection
private import semmle.code.java.security.RequestForgery
private import semmle.code.java.dataflow.internal.ModelExclusions as ModelExclusions
private import AutomodelJavaUtil as AutomodelJavaUtil
import AutomodelSharedCharacteristics as SharedCharacteristics
import AutomodelEndpointTypes as AutomodelEndpointTypes
newtype JavaRelatedLocationType =
MethodDoc() or
ClassDoc()
newtype TFrameworkModeEndpoint =
TExplicitParameter(Parameter p) {
AutomodelJavaUtil::isFromSource(p) and
not AutomodelJavaUtil::isUnexploitableType(p.getType())
} or
TQualifier(Callable c) { AutomodelJavaUtil::isFromSource(c) and not c instanceof Constructor } or
TReturnValue(Callable c) {
AutomodelJavaUtil::isFromSource(c) and
c instanceof Constructor
or
AutomodelJavaUtil::isFromSource(c) and
c instanceof Method and
not AutomodelJavaUtil::isUnexploitableType(c.getReturnType())
} or
TOverridableParameter(Method m, Parameter p) {
AutomodelJavaUtil::isFromSource(p) and
not AutomodelJavaUtil::isUnexploitableType(p.getType()) and
p.getCallable() = m and
m instanceof ModelExclusions::ModelApi and
AutomodelJavaUtil::isOverridable(m)
} or
TOverridableQualifier(Method m) {
AutomodelJavaUtil::isFromSource(m) and
m instanceof ModelExclusions::ModelApi and
AutomodelJavaUtil::isOverridable(m)
}
/**
* A framework mode endpoint.
*/
abstract class FrameworkModeEndpoint extends TFrameworkModeEndpoint {
/**
* Gets the input (if any) for this endpoint, eg.: `Argument[0]`.
*
* For endpoints that are source candidates, this will be `none()`.
*/
abstract string getMaDInput();
/**
* Gets the output (if any) for this endpoint, eg.: `ReturnValue`.
*
* For endpoints that are sink candidates, this will be `none()`.
*/
abstract string getMaDOutput();
/**
* Returns the name of the parameter of the endpoint.
*/
abstract string getParamName();
/**
* Returns the callable that contains the endpoint.
*/
abstract Callable getCallable();
abstract Top asTop();
abstract string getExtensibleType();
string toString() { result = this.asTop().toString() }
Location getLocation() { result = this.asTop().getLocation() }
}
class ExplicitParameterEndpoint extends FrameworkModeEndpoint, TExplicitParameter {
Parameter param;
ExplicitParameterEndpoint() { this = TExplicitParameter(param) and param.fromSource() }
override string getMaDInput() { result = "Argument[" + param.getPosition() + "]" }
override string getMaDOutput() { none() }
override string getParamName() { result = param.getName() }
override Callable getCallable() { result = param.getCallable() }
override Top asTop() { result = param }
override string getExtensibleType() { result = "sinkModel" }
}
class QualifierEndpoint extends FrameworkModeEndpoint, TQualifier {
Callable callable;
QualifierEndpoint() {
this = TQualifier(callable) and not callable.isStatic() and callable.fromSource()
}
override string getMaDInput() { result = "Argument[this]" }
override string getMaDOutput() { none() }
override string getParamName() { result = "this" }
override Callable getCallable() { result = callable }
override Top asTop() { result = callable }
override string getExtensibleType() { result = "sinkModel" }
}
class ReturnValue extends FrameworkModeEndpoint, TReturnValue {
Callable callable;
ReturnValue() { this = TReturnValue(callable) and callable.fromSource() }
override string getMaDInput() { none() }
override string getMaDOutput() { result = "ReturnValue" }
override string getParamName() { none() }
override Callable getCallable() { result = callable }
override Top asTop() { result = callable }
override string getExtensibleType() { result = "sourceModel" }
}
class OverridableParameter extends FrameworkModeEndpoint, TOverridableParameter {
Method method;
Parameter param;
OverridableParameter() { this = TOverridableParameter(method, param) }
override string getMaDInput() { none() }
override string getMaDOutput() { result = "Parameter[" + param.getPosition() + "]" }
override string getParamName() { result = param.getName() }
override Callable getCallable() { result = method }
override Top asTop() { result = param }
override string getExtensibleType() { result = "sourceModel" }
}
class OverridableQualifier extends FrameworkModeEndpoint, TOverridableQualifier {
Method m;
OverridableQualifier() { this = TOverridableQualifier(m) }
override string getMaDInput() { none() }
override string getMaDOutput() { result = "Parameter[this]" }
override string getParamName() { result = "this" }
override Callable getCallable() { result = m }
override Top asTop() { result = m }
override string getExtensibleType() { result = "sourceModel" }
}
/**
* A candidates implementation for framework mode.
*
* Some important notes:
* - This mode is using parameters as endpoints.
* - Sink- and neutral-information is being used from MaD models.
* - When available, we use method- and class-java-docs as related locations.
*/
module FrameworkCandidatesImpl implements SharedCharacteristics::CandidateSig {
// for documentation of the implementations here, see the QLDoc in the CandidateSig signature module.
class Endpoint = FrameworkModeEndpoint;
class EndpointType = AutomodelEndpointTypes::EndpointType;
class SinkType = AutomodelEndpointTypes::SinkType;
class SourceType = AutomodelEndpointTypes::SourceType;
class RelatedLocation = Location::Top;
class RelatedLocationType = JavaRelatedLocationType;
// Sanitizers are currently not modeled in MaD. TODO: check if this has large negative impact.
predicate isSanitizer(Endpoint e, EndpointType t) { none() }
RelatedLocation asLocation(Endpoint e) { result = e.asTop() }
predicate isKnownKind = AutomodelJavaUtil::isKnownKind/2;
predicate isSink(Endpoint e, string kind, string provenance) {
exists(
string package, string type, boolean subtypes, string name, string signature, string ext,
string input
|
sinkSpec(e, package, type, subtypes, name, signature, ext, input) and
ExternalFlow::sinkModel(package, type, subtypes, name, [signature, ""], ext, input, kind,
provenance, _)
)
}
predicate isSource(Endpoint e, string kind, string provenance) {
exists(
string package, string type, boolean subtypes, string name, string signature, string ext,
string output
|
sourceSpec(e, package, type, subtypes, name, signature, ext, output) and
ExternalFlow::sourceModel(package, type, subtypes, name, [signature, ""], ext, output, kind,
provenance, _)
)
}
predicate isNeutral(Endpoint e) {
exists(string package, string type, string name, string signature, string endpointType |
sinkSpec(e, package, type, _, name, signature, _, _) and
endpointType = "sink"
or
sourceSpec(e, package, type, _, name, signature, _, _) and
endpointType = "source"
|
ExternalFlow::neutralModel(package, type, name, [signature, ""], endpointType, _)
)
}
/**
* Holds if the endpoint concerns a callable with the given package, type, name and signature.
*
* If `subtypes` is `false`, only the exact callable is considered. If `true`, the callable and
* all its overrides are considered.
*/
additional predicate endpointCallable(
Endpoint e, string package, string type, boolean subtypes, string name, string signature
) {
exists(Callable c |
c = e.getCallable() and subtypes in [true, false]
or
e.getCallable().(Method).getSourceDeclaration().overrides+(c) and subtypes = true
|
c.hasQualifiedName(package, type, name) and
signature = ExternalFlow::paramsString(c)
)
}
additional predicate sinkSpec(
Endpoint e, string package, string type, boolean subtypes, string name, string signature,
string ext, string input
) {
endpointCallable(e, package, type, subtypes, name, signature) and
ext = "" and
input = e.getMaDInput()
}
additional predicate sourceSpec(
Endpoint e, string package, string type, boolean subtypes, string name, string signature,
string ext, string output
) {
endpointCallable(e, package, type, subtypes, name, signature) and
ext = "" and
output = e.getMaDOutput()
}
/**
* Gets the related location for the given endpoint.
*
* Related locations can be JavaDoc comments of the class or the method.
*/
RelatedLocation getRelatedLocation(Endpoint e, RelatedLocationType type) {
type = MethodDoc() and
result = e.getCallable().(Documentable).getJavadoc()
or
type = ClassDoc() and
result = e.getCallable().getDeclaringType().(Documentable).getJavadoc()
}
}
module CharacteristicsImpl = SharedCharacteristics::SharedCharacteristics<FrameworkCandidatesImpl>;
class EndpointCharacteristic = CharacteristicsImpl::EndpointCharacteristic;
class Endpoint = FrameworkCandidatesImpl::Endpoint;
/*
* Predicates that are used to surface prompt examples and candidates for classification with an ML model.
*/
/**
* A MetadataExtractor that extracts metadata for framework mode.
*/
class FrameworkModeMetadataExtractor extends string {
FrameworkModeMetadataExtractor() { this = "FrameworkModeMetadataExtractor" }
predicate hasMetadata(
Endpoint e, string package, string type, string subtypes, string name, string signature,
string input, string output, string parameterName, string alreadyAiModeled,
string extensibleType
) {
exists(Callable callable | e.getCallable() = callable |
(if exists(e.getMaDInput()) then input = e.getMaDInput() else input = "") and
(if exists(e.getMaDOutput()) then output = e.getMaDOutput() else output = "") and
package = callable.getDeclaringType().getPackage().getName() and
// we're using the erased types because the MaD convention is to not specify type parameters.
// Whether something is or isn't a sink doesn't usually depend on the type parameters.
type = callable.getDeclaringType().getErasure().(RefType).getNestedName() and
subtypes = AutomodelJavaUtil::considerSubtypes(callable).toString() and
name = callable.getName() and
signature = ExternalFlow::paramsString(callable) and
(if exists(e.getParamName()) then parameterName = e.getParamName() else parameterName = "") and
e.getExtensibleType() = extensibleType
) and
(
not CharacteristicsImpl::isModeled(e, _, extensibleType, _) and alreadyAiModeled = ""
or
CharacteristicsImpl::isModeled(e, _, extensibleType, alreadyAiModeled)
)
}
}
/**
* Holds if the given `endpoint` should be considered a candidate for the `extensibleType`.
*
* The other parameters record various other properties of interest.
*/
predicate isCandidate(
Endpoint endpoint, string package, string type, string subtypes, string name, string signature,
string input, string output, string parameterName, string extensibleType, string alreadyAiModeled
) {
CharacteristicsImpl::isCandidate(endpoint, _) and
not exists(CharacteristicsImpl::UninterestingToModelCharacteristic u |
u.appliesToEndpoint(endpoint)
) and
any(FrameworkModeMetadataExtractor meta)
.hasMetadata(endpoint, package, type, subtypes, name, signature, input, output, parameterName,
alreadyAiModeled, extensibleType) and
// If a node is already modeled in MaD, we don't include it as a candidate. Otherwise, we might include it as a
// candidate for query A, but the model will label it as a sink for one of the sink types of query B, for which it's
// already a known sink. This would result in overlap between our detected sinks and the pre-existing modeling. We
// assume that, if a sink has already been modeled in a MaD model, then it doesn't belong to any additional sink
// types, and we don't need to reexamine it.
alreadyAiModeled.matches(["", "%ai-%"]) and
AutomodelJavaUtil::includeAutomodelCandidate(package, type, name, signature)
}
/**
* Holds if the given `endpoint` is a negative example for the `extensibleType`
* because of the `characteristic`.
*
* The other parameters record various other properties of interest.
*/
predicate isNegativeExample(
Endpoint endpoint, EndpointCharacteristic characteristic, float confidence, string package,
string type, string subtypes, string name, string signature, string input, string output,
string parameterName, string extensibleType
) {
characteristic.appliesToEndpoint(endpoint) and
// the node is known not to be an endpoint of any appropriate type
forall(AutomodelEndpointTypes::EndpointType tp |
tp = CharacteristicsImpl::getAPotentialType(endpoint)
|
characteristic.hasImplications(tp, false, _)
) and
// the lowest confidence across all endpoint types should be at least highConfidence
confidence =
min(float c |
characteristic.hasImplications(CharacteristicsImpl::getAPotentialType(endpoint), false, c)
) and
confidence >= SharedCharacteristics::highConfidence() and
any(FrameworkModeMetadataExtractor meta)
.hasMetadata(endpoint, package, type, subtypes, name, signature, input, output, parameterName,
_, extensibleType) and
// It's valid for a node to be both a potential source/sanitizer and a sink. We don't want to include such nodes
// as negative examples in the prompt, because they're ambiguous and might confuse the model, so we explicitly exclude them here.
not exists(EndpointCharacteristic characteristic2, float confidence2 |
characteristic2 != characteristic
|
characteristic2.appliesToEndpoint(endpoint) and
confidence2 >= SharedCharacteristics::maximalConfidence() and
characteristic2
.hasImplications(CharacteristicsImpl::getAPotentialType(endpoint), true, confidence2)
)
}
/**
* Holds if the given `endpoint` is a positive example for the `endpointType`.
*
* The other parameters record various other properties of interest.
*/
predicate isPositiveExample(
Endpoint endpoint, string endpointType, string package, string type, string subtypes, string name,
string signature, string input, string output, string parameterName, string extensibleType
) {
any(FrameworkModeMetadataExtractor meta)
.hasMetadata(endpoint, package, type, subtypes, name, signature, input, output, parameterName,
_, extensibleType) and
CharacteristicsImpl::isKnownAs(endpoint, endpointType, _)
}
/*
* EndpointCharacteristic classes that are specific to Automodel for Java.
*/
/**
* A negative characteristic that indicates that parameters of an is-style boolean method should not be considered sinks,
* and its return value should not be considered a source.
*
* A sink is highly unlikely to be exploitable if its callable's name starts with `is` and the callable has a boolean return
* type (e.g. `isDirectory`). These kinds of calls normally do only checks, and appear before the proper call that does
* the dangerous/interesting thing, so we want the latter to be modeled as the sink.
*
* TODO: this might filter too much, it's possible that methods with more than one parameter contain interesting sinks
*/
private class UnexploitableIsCharacteristic extends CharacteristicsImpl::NeitherSourceNorSinkCharacteristic
{
UnexploitableIsCharacteristic() { this = "argument of is-style boolean method" }
override predicate appliesToEndpoint(Endpoint e) {
e.getCallable().getName().matches("is%") and
e.getCallable().getReturnType() instanceof BooleanType and
(
e.getExtensibleType() = "sinkModel" and
not FrameworkCandidatesImpl::isSink(e, _, _)
or
e.getExtensibleType() = "sourceModel" and
not FrameworkCandidatesImpl::isSource(e, _, _) and
e.getMaDOutput() = "ReturnValue"
)
}
}
/**
* A negative characteristic that indicates that parameters of an existence-checking boolean method should not be
* considered sinks, and its return value should not be considered a source.
*
* A sink is highly unlikely to be exploitable if its callable's name is `exists` or `notExists` and the callable has a
* boolean return type. These kinds of calls normally do only checks, and appear before the proper call that does the
* dangerous/interesting thing, so we want the latter to be modeled as the sink.
*/
private class UnexploitableExistsCharacteristic extends CharacteristicsImpl::NeitherSourceNorSinkCharacteristic
{
UnexploitableExistsCharacteristic() { this = "argument of existence-checking boolean method" }
override predicate appliesToEndpoint(Endpoint e) {
exists(Callable callable |
callable = e.getCallable() and
callable.getName().toLowerCase() = ["exists", "notexists"] and
callable.getReturnType() instanceof BooleanType
|
e.getExtensibleType() = "sinkModel" and
not FrameworkCandidatesImpl::isSink(e, _, _)
or
e.getExtensibleType() = "sourceModel" and
not FrameworkCandidatesImpl::isSource(e, _, _) and
e.getMaDOutput() = "ReturnValue"
)
}
}
/**
* A negative characteristic that indicates that parameters of an exception method or constructor should not be considered sinks,
* and its return value should not be considered a source.
*/
private class ExceptionCharacteristic extends CharacteristicsImpl::NeitherSourceNorSinkCharacteristic
{
ExceptionCharacteristic() { this = "argument/result of exception-related method" }
override predicate appliesToEndpoint(Endpoint e) {
e.getCallable().getDeclaringType().getASupertype*() instanceof TypeThrowable and
(
e.getExtensibleType() = "sinkModel" and
not FrameworkCandidatesImpl::isSink(e, _, _)
or
e.getExtensibleType() = "sourceModel" and
not FrameworkCandidatesImpl::isSource(e, _, _) and
e.getMaDOutput() = "ReturnValue"
)
}
}
/**
* A characteristic that limits candidates to parameters of methods that are recognized as `ModelApi`, iow., APIs that
* are considered worth modeling.
*/
private class NotAModelApi extends CharacteristicsImpl::UninterestingToModelCharacteristic {
NotAModelApi() { this = "not a model API" }
override predicate appliesToEndpoint(Endpoint e) {
not e.getCallable() instanceof ModelExclusions::ModelApi
}
}

View File

@@ -1,38 +0,0 @@
/**
* Surfaces the endpoints that are not already known to be sinks, and are therefore used as candidates for
* classification with an ML model.
*
* Note: This query does not actually classify the endpoints using the model.
*
* @name Automodel candidates (framework mode)
* @description A query to extract automodel candidates in framework mode.
* @kind problem
* @problem.severity recommendation
* @id java/ml/extract-automodel-framework-candidates
* @tags internal extract automodel framework-mode candidates
*/
private import AutomodelFrameworkModeCharacteristics
private import AutomodelJavaUtil
from
Endpoint endpoint, DollarAtString package, DollarAtString type, DollarAtString subtypes,
DollarAtString name, DollarAtString signature, DollarAtString input, DollarAtString output,
DollarAtString parameterName, DollarAtString alreadyAiModeled, DollarAtString extensibleType
where
isCandidate(endpoint, package, type, subtypes, name, signature, input, output, parameterName,
extensibleType, alreadyAiModeled)
select endpoint,
"Related locations: $@, $@." + "\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@.", //
CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, MethodDoc()), "MethodDoc", //
CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, ClassDoc()), "ClassDoc", //
package, "package", //
type, "type", //
subtypes, "subtypes", //
name, "name", //
signature, "signature", //
input, "input", //
output, "output", //
parameterName, "parameterName", //
alreadyAiModeled, "alreadyAiModeled", //
extensibleType, "extensibleType"

View File

@@ -1,36 +0,0 @@
/**
* Surfaces endpoints that are non-sinks with high confidence, for use as negative examples in the prompt.
*
* @name Negative examples (framework mode)
* @kind problem
* @problem.severity recommendation
* @id java/ml/extract-automodel-framework-negative-examples
* @tags internal extract automodel framework-mode negative examples
*/
private import AutomodelFrameworkModeCharacteristics
private import AutomodelEndpointTypes
private import AutomodelJavaUtil
from
Endpoint endpoint, EndpointCharacteristic characteristic, float confidence,
DollarAtString package, DollarAtString type, DollarAtString subtypes, DollarAtString name,
DollarAtString signature, DollarAtString input, DollarAtString output,
DollarAtString parameterName, DollarAtString extensibleType
where
isNegativeExample(endpoint, characteristic, confidence, package, type, subtypes, name, signature,
input, output, parameterName, extensibleType)
select endpoint,
characteristic + "\nrelated locations: $@, $@." +
"\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@.", //
CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, MethodDoc()), "MethodDoc", //
CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, ClassDoc()), "ClassDoc", //
package, "package", //
type, "type", //
subtypes, "subtypes", //
name, "name", //
signature, "signature", //
input, "input", //
output, "output", //
parameterName, "parameterName", //
extensibleType, "extensibleType"

View File

@@ -1,34 +0,0 @@
/**
* Surfaces endpoints that are sinks with high confidence, for use as positive examples in the prompt.
*
* @name Positive examples (framework mode)
* @kind problem
* @problem.severity recommendation
* @id java/ml/extract-automodel-framework-positive-examples
* @tags internal extract automodel framework-mode positive examples
*/
private import AutomodelFrameworkModeCharacteristics
private import AutomodelEndpointTypes
private import AutomodelJavaUtil
from
Endpoint endpoint, EndpointType endpointType, DollarAtString package, DollarAtString type,
DollarAtString subtypes, DollarAtString name, DollarAtString signature, DollarAtString input,
DollarAtString output, DollarAtString parameterName, DollarAtString extensibleType
where
isPositiveExample(endpoint, endpointType, package, type, subtypes, name, signature, input, output,
parameterName, extensibleType)
select endpoint,
endpointType + "\nrelated locations: $@, $@." + "\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@.", //
CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, MethodDoc()), "MethodDoc", //
CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, ClassDoc()), "ClassDoc", //
package, "package", //
type, "type", //
subtypes, "subtypes", //
name, "name", //
signature, "signature", //
input, "input", //
output, "output", //
parameterName, "parameterName", //
extensibleType, "extensibleType"

View File

@@ -1,111 +0,0 @@
private import java
private import AutomodelEndpointTypes as AutomodelEndpointTypes
/**
* A helper class to represent a string value that can be returned by a query using $@ notation.
*
* It extends `string`, but adds a mock `hasLocationInfo` method that returns the string itself as the file name.
*
* Use this, when you want to return a string value from a query using $@ notation - the string value
* will be included in the sarif file.
*
*
* Background information on `hasLocationInfo`:
* https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/#providing-location-information
*/
class DollarAtString extends string {
bindingset[this]
DollarAtString() { any() }
bindingset[this]
predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) {
path = this and sl = 1 and sc = 1 and el = 1 and ec = 1
}
}
/**
* Holds for all combinations of MaD kinds (`kind`) and their human readable
* descriptions.
*/
predicate isKnownKind(string kind, AutomodelEndpointTypes::EndpointType type) {
kind = type.getKind()
}
/**
* By convention, the subtypes property of the MaD declaration should only be
* true when there _can_ exist any subtypes with a different implementation.
*
* It would technically be ok to always use the value 'true', but this would
* break convention.
*/
pragma[nomagic]
boolean considerSubtypes(Callable callable) {
if
callable.isStatic() or
callable.getDeclaringType().isStatic() or
callable.isFinal() or
callable.getDeclaringType().isFinal()
then result = false
else result = true
}
/**
* Holds if the given package, type, name and signature is a candidate for automodeling.
*
* This predicate is extensible, so that different endpoints can be selected at runtime.
*/
extensible predicate automodelCandidateFilter(
string package, string type, string name, string signature
);
/**
* Holds if the given package, type, name and signature is a candidate for automodeling.
*
* This relies on an extensible predicate, and if that is not supplied then
* all endpoints are considered candidates.
*/
bindingset[package, type, name, signature]
predicate includeAutomodelCandidate(string package, string type, string name, string signature) {
not automodelCandidateFilter(_, _, _, _) or
automodelCandidateFilter(package, type, name, signature)
}
/**
* Holds if the given program element corresponds to a piece of source code,
* that is, it is not compiler-generated.
*
* Note: This is a stricter check than `Element::fromSource`, which simply
* checks whether the element is in a source file as opposed to a JAR file.
* There can be compiler-generated elements in source files (especially for
* Kotlin), which we also want to exclude.
*/
predicate isFromSource(Element e) {
// from a source file (not a JAR)
e.fromSource() and
// not explicitly marked as compiler-generated
not e.isCompilerGenerated() and
// does not have a dummy location
not e.hasLocationInfo(_, 0, 0, 0, 0)
}
/**
* Holds if taint cannot flow through the given type (because it is a numeric
* type or some other type with a fixed set of values).
*/
predicate isUnexploitableType(Type tp) {
tp instanceof PrimitiveType or
tp instanceof BoxedType or
tp instanceof NumberType or
tp instanceof VoidType
}
/**
* Holds if the given method can be overridden, that is, it is not final,
* static, or private.
*/
predicate isOverridable(Method m) {
not m.getDeclaringType().isFinal() and
not m.isFinal() and
not m.isStatic() and
not m.isPrivate()
}

View File

@@ -1,412 +0,0 @@
float maximalConfidence() { result = 1.0 }
float highConfidence() { result = 0.9 }
float mediumConfidence() { result = 0.6 }
/**
* A specification of how to instantiate the shared characteristics for a given candidate class.
*
* The `CandidateSig` implementation specifies a type to use for Endpoints (eg., `ParameterNode`), as well as a type
* to label endpoint classes (the `EndpointType`). One of the endpoint classes needs to be a 'negative' class, meaning
* "not any of the other known endpoint types".
*/
signature module CandidateSig {
/**
* An endpoint is a potential candidate for modeling. This will typically be bound to the language's
* DataFlow node class, or a subtype thereof.
*/
class Endpoint {
/**
* Gets the kind of this endpoint, either "sourceModel" or "sinkModel".
*/
string getExtensibleType();
/**
* Gets a string representation of this endpoint.
*/
string toString();
}
/**
* A related location for an endpoint. This will typically be bound to the supertype of all AST nodes (eg., `Top`).
*/
class RelatedLocation;
/**
* A label for a related location.
*
* Eg., method-doc, class-doc, etc.
*/
class RelatedLocationType;
/**
* An endpoint type considered by this specification.
*/
class EndpointType extends string;
/**
* A sink endpoint type considered by this specification.
*/
class SinkType extends EndpointType;
/**
* A source endpoint type considered by this specification.
*/
class SourceType extends EndpointType;
/**
* Gets the endpoint as a location.
*
* This is a utility function to convert an endpoint to its corresponding location.
*/
RelatedLocation asLocation(Endpoint e);
/**
* Defines what MaD kinds are known, and what endpoint type they correspond to.
*/
predicate isKnownKind(string kind, EndpointType type);
/**
* Holds if `e` is a flow sanitizer, and has type `t`.
*/
predicate isSanitizer(Endpoint e, EndpointType t);
/**
* Holds if `e` is a sink with the label `kind`, and provenance `provenance`.
*/
predicate isSink(Endpoint e, string kind, string provenance);
/**
* Holds if `e` is a source with the label `kind`, and provenance `provenance`.
*/
predicate isSource(Endpoint e, string kind, string provenance);
/**
* Holds if `e` is not a source or sink of any kind.
*/
predicate isNeutral(Endpoint e);
/**
* Gets a related location.
*
* A related location is a source code location that may hold extra information about an endpoint that can be useful
* to the machine learning model.
*
* For example, a related location for a method call may be the documentation comment of a method.
*/
RelatedLocation getRelatedLocation(Endpoint e, RelatedLocationType name);
}
/**
* A set of shared characteristics for a given candidate class.
*
* This module is language-agnostic, although the `CandidateSig` module will be language-specific.
*
* The language specific implementation can also further extend the behavior of this module by adding additional
* implementations of endpoint characteristics exported by this module.
*/
module SharedCharacteristics<CandidateSig Candidate> {
predicate isSink = Candidate::isSink/3;
predicate isNeutral = Candidate::isNeutral/1;
predicate isModeled(Candidate::Endpoint e, string kind, string extensibleKind, string provenance) {
Candidate::isSink(e, kind, provenance) and extensibleKind = "sinkModel"
or
Candidate::isSource(e, kind, provenance) and extensibleKind = "sourceModel"
}
/**
* Holds if `endpoint` is modeled as `endpointType`.
*/
predicate isKnownAs(
Candidate::Endpoint endpoint, Candidate::EndpointType endpointType,
EndpointCharacteristic characteristic
) {
// If the list of characteristics includes positive indicators with maximal confidence for this class, then it's a
// known sink for the class.
characteristic.appliesToEndpoint(endpoint) and
characteristic.hasImplications(endpointType, true, maximalConfidence())
}
/**
* Gets a potential type of this endpoint to make sure that sources are
* associated with source types and sinks with sink types.
*/
Candidate::EndpointType getAPotentialType(Candidate::Endpoint endpoint) {
endpoint.getExtensibleType() = "sourceModel" and
result instanceof Candidate::SourceType
or
endpoint.getExtensibleType() = "sinkModel" and
result instanceof Candidate::SinkType
}
/**
* Holds if the given `endpoint` should be considered as a candidate for type `endpointType`,
* and classified by the ML model.
*
* A candidate is an endpoint that cannot be excluded from `endpointType` based on its characteristics.
*/
predicate isCandidate(Candidate::Endpoint endpoint, Candidate::EndpointType endpointType) {
endpointType = getAPotentialType(endpoint) and
not exists(getAnExcludingCharacteristic(endpoint, endpointType))
}
/**
* Gets the related location of `e` with name `name`, if it exists.
* Otherwise, gets the candidate itself.
*/
Candidate::RelatedLocation getRelatedLocationOrCandidate(
Candidate::Endpoint e, Candidate::RelatedLocationType type
) {
if exists(Candidate::getRelatedLocation(e, type))
then result = Candidate::getRelatedLocation(e, type)
else result = Candidate::asLocation(e)
}
/**
* Gets a characteristics that disbar `endpoint` from being a candidate for `endpointType`
* with at least medium confidence.
*/
EndpointCharacteristic getAnExcludingCharacteristic(
Candidate::Endpoint endpoint, Candidate::EndpointType endpointType
) {
result.appliesToEndpoint(endpoint) and
exists(float confidence |
confidence >= mediumConfidence() and
result.hasImplications(endpointType, false, confidence)
)
}
/**
* A set of characteristics that a particular endpoint might have. This set of characteristics is used to make decisions
* about whether to include the endpoint in the training set and with what kind, as well as whether to score the
* endpoint at inference time.
*/
abstract class EndpointCharacteristic extends string {
/**
* Holds for the string that is the name of the characteristic. This should describe some property of an endpoint
* that is meaningful for determining whether it's a sink, and if so, of which sink type.
*/
bindingset[this]
EndpointCharacteristic() { any() }
/**
* Holds for endpoints that have this characteristic.
*/
abstract predicate appliesToEndpoint(Candidate::Endpoint n);
/**
* This predicate describes what the characteristic tells us about an endpoint.
*
* Params:
* endpointType: The sink/source type.
* isPositiveIndicator: If true, this characteristic indicates that this endpoint _is_ a member of the class; if
* false, it indicates that it _isn't_ a member of the class.
* confidence: A float in [0, 1], which tells us how strong an indicator this characteristic is for the endpoint
* belonging / not belonging to the given class. A confidence near zero means this characteristic is a very weak
* indicator of whether or not the endpoint belongs to the class. A confidence of 1 means that all endpoints with
* this characteristic definitively do/don't belong to the class.
*/
abstract predicate hasImplications(
Candidate::EndpointType endpointType, boolean isPositiveIndicator, float confidence
);
/** Indicators with confidence at or above this threshold are considered to be high-confidence indicators. */
final float getHighConfidenceThreshold() { result = 0.8 }
}
/**
* A high-confidence characteristic that indicates that an endpoint is a sink of a specified type. These endpoints can
* be used as positive samples for training or for a few-shot prompt.
*/
abstract class SinkCharacteristic extends EndpointCharacteristic {
bindingset[this]
SinkCharacteristic() { any() }
abstract Candidate::EndpointType getSinkType();
final override predicate hasImplications(
Candidate::EndpointType endpointType, boolean isPositiveIndicator, float confidence
) {
endpointType = this.getSinkType() and
isPositiveIndicator = true and
confidence = maximalConfidence()
}
}
/**
* A high-confidence characteristic that indicates that an endpoint is a source of a specified type. These endpoints can
* be used as positive samples for training or for a few-shot prompt.
*/
abstract class SourceCharacteristic extends EndpointCharacteristic {
bindingset[this]
SourceCharacteristic() { any() }
abstract Candidate::EndpointType getSourceType();
final override predicate hasImplications(
Candidate::EndpointType endpointType, boolean isPositiveIndicator, float confidence
) {
endpointType = this.getSourceType() and
isPositiveIndicator = true and
confidence = maximalConfidence()
}
}
/**
* A high-confidence characteristic that indicates that an endpoint is not a sink of any type. These endpoints can be
* used as negative samples for training or for a few-shot prompt.
*/
abstract class NotASinkCharacteristic extends EndpointCharacteristic {
bindingset[this]
NotASinkCharacteristic() { any() }
override predicate hasImplications(
Candidate::EndpointType endpointType, boolean isPositiveIndicator, float confidence
) {
endpointType instanceof Candidate::SinkType and
isPositiveIndicator = false and
confidence = highConfidence()
}
}
/**
* A high-confidence characteristic that indicates that an endpoint is not a source of any type. These endpoints can be
* used as negative samples for training or for a few-shot prompt.
*/
abstract class NotASourceCharacteristic extends EndpointCharacteristic {
bindingset[this]
NotASourceCharacteristic() { any() }
override predicate hasImplications(
Candidate::EndpointType endpointType, boolean isPositiveIndicator, float confidence
) {
endpointType instanceof Candidate::SourceType and
isPositiveIndicator = false and
confidence = highConfidence()
}
}
/**
* A high-confidence characteristic that indicates that an endpoint is neither a source nor a sink of any type.
*/
abstract class NeitherSourceNorSinkCharacteristic extends NotASinkCharacteristic,
NotASourceCharacteristic
{
bindingset[this]
NeitherSourceNorSinkCharacteristic() { any() }
final override predicate hasImplications(
Candidate::EndpointType endpointType, boolean isPositiveIndicator, float confidence
) {
NotASinkCharacteristic.super.hasImplications(endpointType, isPositiveIndicator, confidence) or
NotASourceCharacteristic.super.hasImplications(endpointType, isPositiveIndicator, confidence)
}
}
/**
* A medium-confidence characteristic that indicates that an endpoint is unlikely to be a sink of any type. These
* endpoints can be excluded from scoring at inference time, both to save time and to avoid false positives. They should
* not, however, be used as negative samples for training or for a few-shot prompt, because they may include a small
* number of sinks.
*/
abstract class LikelyNotASinkCharacteristic extends EndpointCharacteristic {
bindingset[this]
LikelyNotASinkCharacteristic() { any() }
override predicate hasImplications(
Candidate::EndpointType endpointType, boolean isPositiveIndicator, float confidence
) {
endpointType instanceof Candidate::SinkType and
isPositiveIndicator = false and
confidence = mediumConfidence()
}
}
/**
* A characteristic that indicates not necessarily that an endpoint is not a sink, but rather that it is not a sink
* that's interesting to model in the standard Java libraries. These filters should be removed when extracting sink
* candidates within a user's codebase for customized modeling.
*
* These endpoints should not be used as negative samples for training or for a few-shot prompt, because they are not
* necessarily non-sinks.
*/
abstract class UninterestingToModelCharacteristic extends EndpointCharacteristic {
bindingset[this]
UninterestingToModelCharacteristic() { any() }
override predicate hasImplications(
Candidate::EndpointType endpointType, boolean isPositiveIndicator, float confidence
) {
endpointType instanceof Candidate::SinkType and
isPositiveIndicator = false and
confidence = mediumConfidence()
}
}
/**
* Contains default implementations that are derived solely from the `CandidateSig` implementation.
*/
private module DefaultCharacteristicImplementations {
/**
* Endpoints identified as sinks by the `CandidateSig` implementation are sinks with maximal confidence.
*/
private class KnownSinkCharacteristic extends SinkCharacteristic {
string madKind;
Candidate::EndpointType endpointType;
string provenance;
KnownSinkCharacteristic() {
Candidate::isKnownKind(madKind, endpointType) and
// bind "this" to a unique string differing from that of the SinkType classes
this = madKind + "_" + provenance + "_characteristic" and
Candidate::isSink(_, madKind, provenance)
}
override predicate appliesToEndpoint(Candidate::Endpoint e) {
Candidate::isSink(e, madKind, provenance)
}
override Candidate::EndpointType getSinkType() { result = endpointType }
}
private class KnownSourceCharacteristic extends SourceCharacteristic {
string madKind;
Candidate::EndpointType endpointType;
string provenance;
KnownSourceCharacteristic() {
Candidate::isKnownKind(madKind, endpointType) and
// bind "this" to a unique string differing from that of the SinkType classes
this = madKind + "_" + provenance + "_characteristic" and
Candidate::isSource(_, madKind, provenance)
}
override predicate appliesToEndpoint(Candidate::Endpoint e) {
Candidate::isSource(e, madKind, provenance)
}
override Candidate::EndpointType getSourceType() { result = endpointType }
}
/**
* A negative characteristic that indicates that an endpoint was manually modeled as a neutral model.
*/
private class NeutralModelCharacteristic extends NeitherSourceNorSinkCharacteristic {
NeutralModelCharacteristic() { this = "known non-sink" }
override predicate appliesToEndpoint(Candidate::Endpoint e) { Candidate::isNeutral(e) }
}
/**
* A negative characteristic that indicates that an endpoint is a sanitizer, and thus not a source.
*/
private class IsSanitizerCharacteristic extends NotASourceCharacteristic {
IsSanitizerCharacteristic() { this = "known sanitizer" }
override predicate appliesToEndpoint(Candidate::Endpoint e) { Candidate::isSanitizer(e, _) }
}
}
}

View File

@@ -1,62 +0,0 @@
/**
* This file contains query predicates for use when gathering metrics at scale using Multi Repo
* Variant Analysis.
*/
private import java
private import AutomodelAlertSinkUtil
/**
* Holds if `alertCount` is the number of alerts for the query with ID `queryId` for which the
* sinks correspond to the given `ai-generated` sink model.
*/
query predicate sinkModelCountPerQuery(
string queryId, int alertCount, string package, string type, boolean subtypes, string name,
string signature, string input, string ext, string kind, string provenance
) {
exists(SinkModel s |
sinkModelTallyPerQuery(queryId, alertCount, s) and
s.getProvenance() = "ai-generated" and
s.getPackage() = package and
s.getType() = type and
s.getSubtypes() = subtypes and
s.getName() = name and
s.getSignature() = signature and
s.getInput() = input and
s.getExt() = ext and
s.getKind() = kind and
s.getProvenance() = provenance
)
}
/**
* Holds if `instanceCount` is the number of instances corresponding to the given `ai-generated`
* sink model (as identified by the `package`, `name`, `input`, etc.).
*/
query predicate instanceCount(
int instanceCount, string package, string type, boolean subtypes, string name, string signature,
string input, string ext, string kind, string provenance
) {
exists(SinkModel s |
instanceCount = s.getInstanceCount() and
instanceCount > 0 and
s.getProvenance() = "ai-generated" and
s.getPackage() = package and
s.getType() = type and
s.getSubtypes() = subtypes and
s.getName() = name and
s.getSignature() = signature and
s.getInput() = input and
s.getExt() = ext and
s.getKind() = kind and
s.getProvenance() = provenance
)
}
// MRVA requires a select clause, so we repurpose it to tell us which query predicates had results.
from string hadResults
where
sinkModelCountPerQuery(_, _, _, _, _, _, _, _, _, _, _) and hadResults = "sinkModelCountPerQuery"
or
instanceCount(_, _, _, _, _, _, _, _, _, _) and hadResults = "instanceCount"
select hadResults

View File

@@ -0,0 +1,4 @@
---
category: breaking
---
* Dropped the Java Automodel queries.

View File

@@ -1,2 +0,0 @@
---
lastReleaseVersion: 1.0.11

View File

@@ -1,10 +0,0 @@
name: codeql/java-automodel-queries
version: 1.0.12-dev
groups:
- java
- automodel
dependencies:
codeql/java-all: ${workspace}
dataExtensions:
- AutomodelCandidateFilter.yml
warnOnImplicitThis: true

View File

@@ -1,35 +0,0 @@
import java
import AutomodelApplicationModeCharacteristics as Characteristics
import AutomodelExtractionTests
module TestHelper implements TestHelperSig<Characteristics::ApplicationCandidatesImpl> {
Location getEndpointLocation(Characteristics::Endpoint endpoint) {
result = endpoint.asTop().getLocation()
}
predicate isCandidate(
Characteristics::Endpoint endpoint, string name, string signature, string input, string output,
string extensibleType
) {
Characteristics::isCandidate(endpoint, _, _, _, name, signature, input, output, _,
extensibleType, _)
}
predicate isPositiveExample(
Characteristics::Endpoint endpoint, string endpointType, string name, string signature,
string input, string output, string extensibleType
) {
Characteristics::isPositiveExample(endpoint, endpointType, _, _, _, name, signature, input,
output, _, extensibleType)
}
predicate isNegativeExample(
Characteristics::Endpoint endpoint, string name, string signature, string input, string output,
string extensibleType
) {
Characteristics::isNegativeExample(endpoint, _, _, _, _, _, name, signature, input, output, _,
extensibleType)
}
}
import MakeTest<Extraction<Characteristics::ApplicationCandidatesImpl, TestHelper>>

View File

@@ -1,8 +0,0 @@
import hudson.Plugin;
public class PluginImpl extends Plugin {
@Override
public void configure(String name, String value) { // $ sourceModelCandidate=configure(String,String):Parameter[0] sourceModelCandidate=configure(String,String):Parameter[1]
// ...
}
}

View File

@@ -1,112 +0,0 @@
package com.github.codeql.test;
import java.io.InputStream;
import java.io.PrintWriter;
import java.nio.file.CopyOption;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;
import java.io.File;
import java.io.FileFilter;
import java.nio.file.FileVisitOption;
import java.net.URLConnection;
import java.util.concurrent.FutureTask;
class Test {
public static void main(String[] args) throws Exception {
AtomicReference<String> reference = new AtomicReference<>(); // uninteresting (parameterless constructor)
reference.set( // $ sinkModelCandidate=set(Object):Argument[this]
args[0] // $ negativeSinkExample=set(Object):Argument[0] // modeled as a flow step
); // not a source candidate (return type is void)
}
public static void callSupplier(Supplier<String> supplier) {
supplier.get(); // not a source candidate (lambda flow)
}
public static void copyFiles(Path source, Path target, CopyOption option) throws Exception {
Files.copy(
source, // $ positiveSinkExample=copy(Path,Path,CopyOption[]):Argument[0](path-injection)
target, // $ positiveSinkExample=copy(Path,Path,CopyOption[]):Argument[1](path-injection)
option // no candidate (not modeled, but source and target are modeled)
); // $ sourceModelCandidate=copy(Path,Path,CopyOption[]):ReturnValue
}
public static InputStream getInputStream(Path openPath) throws Exception {
return Files.newInputStream(
openPath // $ sinkModelCandidate=newInputStream(Path,OpenOption[]):Argument[0] positiveSinkExample=newInputStream(Path,OpenOption[]):Argument[0](path-injection) // sink candidate because "only" ai-modeled, and useful as a candidate in regression testing
); // $ sourceModelCandidate=newInputStream(Path,OpenOption[]):ReturnValue
}
public static InputStream getInputStream(String openPath, String otherPath) throws Exception {
return Test.getInputStream( // the call is not a source candidate (argument to local call)
Paths.get(
openPath, // $ negativeSinkExample=get(String,String[]):Argument[0] // modeled as a flow step
otherPath
) // $ sourceModelCandidate=get(String,String[]):ReturnValue negativeSinkExample=get(String,String[]):Argument[1]
);
}
public static int compareFiles(File f1, File f2) {
return f1.compareTo( // $ negativeSinkExample=compareTo(File):Argument[this]
f2 // $ negativeSinkExample=compareTo(File):Argument[0] // modeled as not a sink
); // not a source candidate (return type is int)
}
public static void FilesWalkExample(Path p, FileVisitOption o) throws Exception {
Files.walk(
p, // $ negativeSinkExample=walk(Path,FileVisitOption[]):Argument[0] // modeled as a flow step
o, // the implicit varargs array is a candidate, annotated on the last line of the call
o // not a candidate (only the first arg corresponding to a varargs array
// is extracted)
); // $ sourceModelCandidate=walk(Path,FileVisitOption[]):ReturnValue sinkModelCandidate=walk(Path,FileVisitOption[]):Argument[1]
}
public static void WebSocketExample(URLConnection c) throws Exception {
c.getInputStream(); // $ sinkModelCandidate=getInputStream():Argument[this] positiveSourceExample=getInputStream():ReturnValue(remote) // not a source candidate (manual modeling)
c.connect(); // $ sinkModelCandidate=connect():Argument[this] // not a source candidate (return type is void)
}
public static void fileFilterExample(File f, FileFilter ff) {
f.listFiles( // $ sinkModelCandidate=listFiles(FileFilter):Argument[this]
ff
); // $ sourceModelCandidate=listFiles(FileFilter):ReturnValue
}
}
class OverrideTest extends Exception {
public void printStackTrace(PrintWriter writer) { // $ sourceModelCandidate=printStackTrace(PrintWriter):Parameter[0]
return;
}
}
class TaskUtils {
public FutureTask getTask() {
FutureTask ft = new FutureTask(() -> {
// ^-- no sink candidate for the `this` qualifier of a constructor
return 42;
});
return ft;
}
}
class MoreTests {
public static void FilesListExample(Path p) throws Exception {
Files.list(
Files.createDirectories(
p // $ positiveSinkExample=createDirectories(Path,FileAttribute[]):Argument[0](path-injection)
) // $ sourceModelCandidate=createDirectories(Path,FileAttribute[]):ReturnValue negativeSinkExample=list(Path):Argument[0] // modeled as a flow step
); // $ sourceModelCandidate=list(Path):ReturnValue
Files.delete(
p // $ sinkModelCandidate=delete(Path):Argument[0] positiveSinkExample=delete(Path):Argument[0](path-injection)
); // not a source candidate (return type is void)
Files.deleteIfExists(
p // $ sinkModelCandidate=deleteIfExists(Path):Argument[0] positiveSinkExample=deleteIfExists(Path):Argument[0](path-injection)
); // not a source candidate (return type is boolean)
}
}

View File

@@ -1,7 +0,0 @@
package hudson;
/** Plugin doc */
public class Plugin {
/** Configure method doc */
public void configure(String name, String value) {}
}

View File

@@ -1,77 +0,0 @@
import java
import TestUtilities.InlineExpectationsTest
import AutomodelSharedCharacteristics
signature module TestHelperSig<CandidateSig Candidate> {
Location getEndpointLocation(Candidate::Endpoint e);
predicate isCandidate(
Candidate::Endpoint e, string name, string signature, string input, string output,
string extensibleType
);
predicate isPositiveExample(
Candidate::Endpoint e, string endpointType, string name, string signature, string input,
string output, string extensibleType
);
predicate isNegativeExample(
Candidate::Endpoint e, string name, string signature, string input, string output,
string extensibleType
);
}
module Extraction<CandidateSig Candidate, TestHelperSig<Candidate> TestHelper> implements TestSig {
string getARelevantTag() {
result in [
"sourceModelCandidate", "sinkModelCandidate", // a candidate source/sink
"positiveSourceExample", "positiveSinkExample", // a known source/sink
"negativeSourceExample", "negativeSinkExample" // a known non-source/non-sink
]
}
/**
* If `extensibleType` is `sourceModel` then the result is `ifSource`, if it
* is `sinkModel` then the result is `ifSink`.
*/
bindingset[extensibleType, ifSource, ifSink]
private string ifSource(string extensibleType, string ifSource, string ifSink) {
extensibleType = "sourceModel" and result = ifSource
or
extensibleType = "sinkModel" and result = ifSink
}
additional predicate selectEndpoint(
Candidate::Endpoint endpoint, string name, string signature, string input, string output,
string extensibleType, string tag, string suffix
) {
TestHelper::isCandidate(endpoint, name, signature, input, output, extensibleType) and
tag = ifSource(extensibleType, "sourceModelCandidate", "sinkModelCandidate") and
suffix = ""
or
TestHelper::isNegativeExample(endpoint, name, signature, input, output, extensibleType) and
tag = "negative" + ifSource(extensibleType, "Source", "Sink") + "Example" and
suffix = ""
or
exists(string endpointType |
TestHelper::isPositiveExample(endpoint, endpointType, name, signature, input, output,
extensibleType) and
tag = "positive" + ifSource(extensibleType, "Source", "Sink") + "Example" and
suffix = "(" + endpointType + ")"
)
}
predicate hasActualResult(Location location, string element, string tag, string value) {
exists(
Candidate::Endpoint endpoint, string name, string signature, string input, string output,
string extensibleType, string suffix
|
selectEndpoint(endpoint, name, signature, input, output, extensibleType, tag, suffix)
|
TestHelper::getEndpointLocation(endpoint) = location and
endpoint.toString() = element and
// for source models only the output is relevant, and vice versa for sink models
value = name + signature + ":" + ifSource(extensibleType, output, input) + suffix
)
}
}

View File

@@ -1,35 +0,0 @@
import java
import AutomodelFrameworkModeCharacteristics as Characteristics
import AutomodelExtractionTests
module TestHelper implements TestHelperSig<Characteristics::FrameworkCandidatesImpl> {
Location getEndpointLocation(Characteristics::Endpoint endpoint) {
result = endpoint.asTop().getLocation()
}
predicate isCandidate(
Characteristics::Endpoint endpoint, string name, string signature, string input, string output,
string extensibleType
) {
Characteristics::isCandidate(endpoint, _, _, _, name, signature, input, output, _,
extensibleType, _)
}
predicate isPositiveExample(
Characteristics::Endpoint endpoint, string endpointType, string name, string signature,
string input, string output, string extensibleType
) {
Characteristics::isPositiveExample(endpoint, endpointType, _, _, _, name, signature, input,
output, _, extensibleType)
}
predicate isNegativeExample(
Characteristics::Endpoint endpoint, string name, string signature, string input, string output,
string extensibleType
) {
Characteristics::isNegativeExample(endpoint, _, _, _, _, _, name, signature, input, output, _,
extensibleType)
}
}
import MakeTest<Extraction<Characteristics::FrameworkCandidatesImpl, TestHelper>>

View File

@@ -1,15 +0,0 @@
package com.github.codeql.test;
public class MyWriter extends java.io.Writer {
@Override
public void write(char[] cbuf, int off, int len) { // $ sinkModelCandidate=write(char[],int,int):Argument[this] positiveSinkExample=write(char[],int,int):Argument[0](file-content-store) sourceModelCandidate=write(char[],int,int):Parameter[this] sourceModelCandidate=write(char[],int,int):Parameter[0]
}
@Override
public void close() { // $ sinkModelCandidate=close():Argument[this] sourceModelCandidate=close():Parameter[this]
}
@Override
public void flush() { // $ sinkModelCandidate=flush():Argument[this] sourceModelCandidate=flush():Parameter[this]
}
}

View File

@@ -1,10 +0,0 @@
package com.github.codeql.test;
/**
* No candidates in this class, as it's not public!
*/
class NonPublicClass {
public void noCandidates(String here) {
System.out.println(here);
}
}

View File

@@ -1,27 +0,0 @@
package com.github.codeql.test;
public class PublicClass {
public void stuff(String arg) { // $ sinkModelCandidate=stuff(String):Argument[this] sourceModelCandidate=stuff(String):Parameter[this] sinkModelCandidate=stuff(String):Argument[0] sourceModelCandidate=stuff(String):Parameter[0] // source candidates because it is an overrideable method
System.out.println(arg);
}
public static void staticStuff(String arg) { // $ sinkModelCandidate=staticStuff(String):Argument[0] // `arg` is not a source candidate (not overrideabe); `this` is not a candidate (static method)
System.out.println(arg);
}
protected void nonPublicStuff(String arg) { // $ sinkModelCandidate=nonPublicStuff(String):Argument[this] sourceModelCandidate=nonPublicStuff(String):Parameter[this] sinkModelCandidate=nonPublicStuff(String):Argument[0] sourceModelCandidate=nonPublicStuff(String):Parameter[0]
System.out.println(arg);
}
void packagePrivateStuff(String arg) { // no candidates because the method is not public
System.out.println(arg);
}
public PublicClass(Object input) { // $ sourceModelCandidate=PublicClass(Object):ReturnValue sinkModelCandidate=PublicClass(Object):Argument[0] // `this` is not a candidate because it is a constructor
}
// `input` and `input` are source candidates, but not sink candidates (is-style method)
public Boolean isIgnored(Object input) { // $ negativeSinkExample=isIgnored(Object):Argument[this] sourceModelCandidate=isIgnored(Object):Parameter[this] negativeSinkExample=isIgnored(Object):Argument[0] sourceModelCandidate=isIgnored(Object):Parameter[0]
return false;
}
}

View File

@@ -1,9 +0,0 @@
package com.github.codeql.test;
public interface PublicInterface {
public int stuff(String arg); // $ sinkModelCandidate=stuff(String):Argument[this] sourceModelCandidate=stuff(String):Parameter[this] sinkModelCandidate=stuff(String):Argument[0] sourceModelCandidate=stuff(String):Parameter[0] // result is _not_ a source candidate source (primitive return type)
public static void staticStuff(String arg) { // $ sinkModelCandidate=staticStuff(String):Argument[0] // not a source candidate (static method)
System.out.println(arg);
}
}

View File

@@ -1,13 +0,0 @@
package java.io;
public class File {
public int compareTo( // $ negativeSinkExample=compareTo(File):Argument[this] sourceModelCandidate=compareTo(File):Parameter[this] // modeled as neutral for sinks
File pathname // $ negativeSinkExample=compareTo(File):Argument[0] sourceModelCandidate=compareTo(File):Parameter[0] // modeled as neutral for sinks
) {
return 0;
}
public boolean setLastModified(long time) { // $ sinkModelCandidate=setLastModified(long):Argument[this] sourceModelCandidate=setLastModified(long):Parameter[this] // time is not a candidate (primitive type)
return false;
} // return value is not a source candidate because it's a primitive
}

View File

@@ -1,31 +0,0 @@
package java.nio.file;
import java.io.InputStream;
import java.io.FileInputStream;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.OpenOption;
public class Files {
public static void copy( // method result is not a candidate source (void)
Path source, // $ positiveSinkExample=copy(Path,OutputStream):Argument[0](path-injection) // manual model exists
OutputStream out // $ sinkModelCandidate=copy(Path,OutputStream):Argument[1]
/* NB: may be worthwhile to implement the
same behavior as in application mode where out would not be a
candidate because there already is a model for another parameter of
the same method and we assume that methods are always modeled
completely.
*/
) throws IOException {
// ...
}
public static InputStream newInputStream( // $ sourceModelCandidate=newInputStream(Path,OpenOption[]):ReturnValue
Path openPath, // $ positiveSinkExample=newInputStream(Path,OpenOption[]):Argument[0](path-injection) sinkModelCandidate=newInputStream(Path,OpenOption[]):Argument[0] // known sink, but still a candidate (ai-modeled, and useful as a candidate in regression testing)
OpenOption... options // $ sinkModelCandidate=newInputStream(Path,OpenOption[]):Argument[1]
) throws IOException {
return new FileInputStream(openPath.toFile());
}
}

View File

@@ -1,4 +0,0 @@
---
category: breaking
---
* CodeQL package management is now generally available, and all GitHub-produced CodeQL packages have had their version numbers increased to 1.0.0.

View File

@@ -1,13 +0,0 @@
name: codeql/java-automodel-tests
version: 1.0.0-dev
groups:
- java
- automodel
- test
dependencies:
codeql/java-all: ${workspace}
codeql/java-automodel-queries: ${workspace}
codeql/java-tests: ${workspace}
extractor: java
tests: .
warnOnImplicitThis: true

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Added taint-steps for `String.prototype.toWellFormed`.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Added taint-steps for `Map.groupBy` and `Object.groupBy`.

View File

@@ -151,4 +151,32 @@ private module CollectionDataFlow {
)
}
}
/**
* A step for a call to `groupBy` on an iterable object.
*/
private class GroupByTaintStep extends TaintTracking::SharedTaintStep {
override predicate heapStep(DataFlow::Node pred, DataFlow::Node succ) {
exists(DataFlow::MethodCallNode call |
call = DataFlow::globalVarRef(["Map", "Object"]).getAMemberCall("groupBy") and
pred = call.getArgument(0) and
(succ = call.getCallback(1).getParameter(0) or succ = call)
)
}
}
/**
* A step for handling data flow and taint tracking for the groupBy method on iterable objects.
* Ensures propagation of taint and data flow through the groupBy operation.
*/
private class GroupByDataFlowStep extends PreCallGraphStep {
override predicate storeStep(DataFlow::Node pred, DataFlow::SourceNode succ, string prop) {
exists(DataFlow::MethodCallNode call |
call = DataFlow::globalVarRef("Map").getAMemberCall("groupBy") and
pred = call.getArgument(0) and
succ = call and
prop = mapValueUnknownKey()
)
}
}
}

View File

@@ -612,7 +612,7 @@ module TaintTracking {
"italics", "link", "padEnd", "padStart", "repeat", "replace", "replaceAll", "slice",
"small", "split", "strike", "sub", "substr", "substring", "sup",
"toLocaleLowerCase", "toLocaleUpperCase", "toLowerCase", "toUpperCase", "trim",
"trimLeft", "trimRight"
"trimLeft", "trimRight", "toWellFormed"
]
or
// sorted, interesting, properties of Object.prototype

View File

@@ -209,6 +209,10 @@ typeInferenceMismatch
| static-capture-groups.js:2:17:2:24 | source() | static-capture-groups.js:27:14:27:22 | RegExp.$1 |
| static-capture-groups.js:32:17:32:24 | source() | static-capture-groups.js:38:10:38:18 | RegExp.$1 |
| static-capture-groups.js:42:12:42:19 | source() | static-capture-groups.js:43:14:43:22 | RegExp.$1 |
| string-immutable-operations.js:2:13:2:20 | source() | string-immutable-operations.js:3:10:3:25 | x.toWellFormed() |
| string-immutable-operations.js:2:13:2:20 | source() | string-immutable-operations.js:6:10:6:20 | wellFormedX |
| string-immutable-operations.js:2:13:2:20 | source() | string-immutable-operations.js:9:10:9:26 | concatWellFormedX |
| string-immutable-operations.js:11:10:11:17 | source() | string-immutable-operations.js:11:10:11:32 | source( ... ormed() |
| string-replace.js:3:13:3:20 | source() | string-replace.js:14:10:14:13 | data |
| string-replace.js:3:13:3:20 | source() | string-replace.js:18:10:18:13 | data |
| string-replace.js:3:13:3:20 | source() | string-replace.js:21:6:21:41 | safe(). ... taint) |
@@ -244,8 +248,19 @@ typeInferenceMismatch
| tst.js:2:13:2:20 | source() | tst.js:66:10:66:16 | xSorted |
| tst.js:2:13:2:20 | source() | tst.js:68:10:68:23 | x.toReversed() |
| tst.js:2:13:2:20 | source() | tst.js:70:10:70:18 | xReversed |
| tst.js:2:13:2:20 | source() | tst.js:72:10:72:17 | x.with() |
| tst.js:2:13:2:20 | source() | tst.js:74:10:74:14 | xWith |
| tst.js:2:13:2:20 | source() | tst.js:72:10:72:31 | Map.gro ... z => z) |
| tst.js:2:13:2:20 | source() | tst.js:74:10:74:34 | Object. ... z => z) |
| tst.js:2:13:2:20 | source() | tst.js:78:55:78:58 | item |
| tst.js:2:13:2:20 | source() | tst.js:79:14:79:20 | grouped |
| tst.js:2:13:2:20 | source() | tst.js:100:10:100:17 | x.with() |
| tst.js:2:13:2:20 | source() | tst.js:102:10:102:14 | xWith |
| tst.js:75:22:75:29 | source() | tst.js:75:10:75:52 | Map.gro ... (item)) |
| tst.js:75:22:75:29 | source() | tst.js:75:47:75:50 | item |
| tst.js:82:23:82:30 | source() | tst.js:83:58:83:61 | item |
| tst.js:82:23:82:30 | source() | tst.js:84:14:84:20 | grouped |
| tst.js:87:22:87:29 | source() | tst.js:90:14:90:25 | taintedValue |
| tst.js:93:22:93:29 | source() | tst.js:96:14:96:25 | taintedValue |
| tst.js:93:22:93:29 | source() | tst.js:97:14:97:26 | map.get(true) |
| xml.js:5:18:5:25 | source() | xml.js:8:14:8:17 | text |
| xml.js:12:17:12:24 | source() | xml.js:13:14:13:19 | result |
| xml.js:23:18:23:25 | source() | xml.js:20:14:20:17 | attr |

View File

@@ -112,3 +112,5 @@
| thisAssignments.js:7:19:7:26 | source() | thisAssignments.js:8:10:8:20 | this.field2 |
| tst.js:2:13:2:20 | source() | tst.js:4:10:4:10 | x |
| tst.js:2:13:2:20 | source() | tst.js:54:14:54:19 | unsafe |
| tst.js:93:22:93:29 | source() | tst.js:96:14:96:25 | taintedValue |
| tst.js:93:22:93:29 | source() | tst.js:97:14:97:26 | map.get(true) |

View File

@@ -0,0 +1,12 @@
function test() {
let x = source();
sink(x.toWellFormed()); // NOT OK
const wellFormedX = x.toWellFormed();
sink(wellFormedX); // NOT OK
const concatWellFormedX = "/" + wellFormedX + "!";
sink(concatWellFormedX); // NOT OK
sink(source().toWellFormed()); // NOT OK
}

View File

@@ -69,6 +69,34 @@ function test() {
const xReversed = x.toReversed();
sink(xReversed) // NOT OK
sink(Map.groupBy(x, z => z)); // NOT OK
sink(Custom.groupBy(x, z => z)); // OK
sink(Object.groupBy(x, z => z)); // NOT OK
sink(Map.groupBy(source(), (item) => sink(item))); // NOT OK
{
const grouped = Map.groupBy(x, (item) => sink(item)); // NOT OK
sink(grouped); // NOT OK
}
{
const list = [source()];
const grouped = Map.groupBy(list, (item) => sink(item)); // NOT OK
sink(grouped); // NOT OK
}
{
const data = source();
const result = Object.groupBy(data, item => item);
const taintedValue = result[notDefined()];
sink(taintedValue); // NOT OK
}
{
const data = source();
const map = Map.groupBy(data, item => item);
const taintedValue = map.get(true);
sink(taintedValue); // NOT OK
sink(map.get(true)); // NOT OK
}
sink(x.with()) // NOT OK
const xWith = x.with();
sink(xWith) // NOT OK

View File

@@ -0,0 +1,4 @@
argumentToEnsureNotTaintedNotMarkedAsSpurious
untaintedArgumentToEnsureTaintedNotMarkedAsMissing
testFailures
failures

View File

@@ -0,0 +1,118 @@
import threading
import time
# Test 1
# TP - Flow is tracked through a global variable
foo1 = None
def bar1():
time.sleep(1)
ensure_tainted(foo1) # $tainted
# The intent of these tests is to test how dataflow is handled through shared state accessed by different threads;
# but the presense or absense of the actual call to start a thread does not affect the results (there is no special modelling for Thread)
# threading.Thread(target=bar).start()
foo1 = TAINTED_STRING
# Test 2
# FN - Flow is *not* tracked through an access path on a global variable
foo2 = []
def bar2():
time.sleep(1)
ensure_tainted(foo2[0]) # $MISSING:tainted
threading.Thread(target=bar2).start()
foo2.append(TAINTED_STRING)
# Test 3
# FN - Flow is not found even when there is a direct call
foo3 = []
def bar3():
time.sleep(1)
ensure_tainted(foo2[0]) # $MISSING:tainted
foo3.append(TAINTED_STRING)
bar3()
# Tast 4
# TP - Sanity check: Flow is found through a ListElement directly without a call
foo4 = []
foo4.append(TAINTED_STRING)
ensure_tainted(foo4[0]) # $tainted
# Test 5
# FN - Flow is *not* tracked through a shared captured but non-global variable
def test5():
foo5 = None
def bar5():
time.sleep(1)
ensure_tainted(foo5) # $MISSING:tainted
threading.Thread(target=bar5).start() # Only the presense of this thread call makes this an FN rather than a TN
foo5 = TAINTED_STRING
# Test 6
# TP - Flow is tracked through a shared captured but non-global variable with a direct call
def test6():
foo6 = []
def bar6():
time.sleep(1)
ensure_tainted(foo6[0]) # $tainted
foo6.append(TAINTED_STRING)
bar6()
# Test 7
# FN - Flow is *not* found through an access path on a global variable that's also used as a parameter
# We'd like to cover this case in order to be able to cover this CVE: https://github.com/github/codeql-python-CVE-coverage/issues/3176
foo7 = []
def bar7():
time.sleep(1)
ensure_tainted(foo7[0]) # $MISSING: tainted
def baz7(loc_foo):
loc_foo.append(TAINTED_STRING)
threading.Thread(target=bar7).start()
baz7(foo7)
# Test 8
# FN - Flow is also *not* found in the above case through a direct call
foo8 = []
def bar8():
time.sleep(1)
ensure_tainted(foo8[0]) # $MISSING: tainted
def baz8(loc_foo):
loc_foo.append(TAINTED_STRING)
baz8(foo8)
bar8()
# Test 9
# TP - Flow is found in the above case when the variable is captured rather than global
def test9():
foo9 = []
def bar9():
time.sleep(1)
ensure_tainted(foo9[0]) # $tainted
def baz9(loc_foo):
loc_foo.append(TAINTED_STRING)
baz9(foo9)
bar9()

View File

@@ -0,0 +1,3 @@
import python
import experimental.meta.InlineTaintTest
import MakeInlineTaintTest<TestTaintTrackingConfig>

View File

@@ -1,4 +1,4 @@
lib/codeql/rust/controlflow/internal/generated/CfgNodes.qll f331c857a9c849ea8e3074446a2633a2dbd042e33c6ecab325f5cab91486204a 497feaf8afce895b24bc7e147199d3b9e6b2ad097f474158a220217d4d68d273
lib/codeql/rust/controlflow/internal/generated/CfgNodes.qll 4005dd5213c45c8f96e12f08d8a6a7532692d68a3cd9e3a0fd55d7f982a92f23 ec753357ac4fc76706acc0cf1d9208e63a0688e480ece52e4314d7dc2a743de5
lib/codeql/rust/elements/Abi.qll 4c973d28b6d628f5959d1f1cc793704572fd0acaae9a97dfce82ff9d73f73476 250f68350180af080f904cd34cb2af481c5c688dc93edf7365fd0ae99855e893
lib/codeql/rust/elements/ArgList.qll 661f5100f5d3ef8351452d9058b663a2a5c720eea8cf11bedd628969741486a2 28e424aac01a90fb58cd6f9f83c7e4cf379eea39e636bc0ba07efc818be71c71
lib/codeql/rust/elements/ArrayExpr.qll a3e6e122632f4011644ec31b37f88b32fe3f2b7e388e7e878a6883309937049f 12ccb5873d95c433da5606fd371d182ef2f71b78d0c53c2d6dec10fa45852bdc
@@ -41,10 +41,10 @@ lib/codeql/rust/elements/FieldList.qll bd243adc4696c60f636055a1c2da28039fe202847
lib/codeql/rust/elements/FnPtrType.qll c4a90dc660cf620972dc23b95494f5caf9f050eabd4bdb52fdc061f8797ba9a1 f8defc91582fa503607664668f9e2e6c2cd8b320c7c449610f21e52e332a129f
lib/codeql/rust/elements/ForExpr.qll 0cc8bfe10b8baf62a1ff65c8463cfb17ab64b41c30c9e1edb962a227df2036d9 b1be73294e6da0f49fd32177ad0b05fecf26081d5ce424f288be99a4bd59cc84
lib/codeql/rust/elements/ForType.qll 0036bed8749358c356d78c4a0eef40d73e2796284293cde5604ae70ddd6d0470 4edcaf8f7c67d42ebe3ebb1be6a7643758717d4fe88f5f648b6a1c5ff4ee4de7
lib/codeql/rust/elements/Format.qll 506172d176f4b965f428585c032464f4abe07a0e47c574f8e011d8641ec45370 653e81bf233b8729649064de64f4a7a8533f8864ac6d2ea913f347088c924c60
lib/codeql/rust/elements/Format.qll 51222fa2d2e85d496ab093d74d3bc606ede3ce48f926106e059dc8478e657203 b4da6be38413c86f2e9d82004624abab16e23ef238197a5c85246009cce276d5
lib/codeql/rust/elements/FormatArgsArg.qll 5bc9b4cd1bac7131165836e93838c45452a08ea6011741cbddace3cbf9c69440 f825140e98dc9800d5c045402186793c7b21511448e2f6bf6402d1e06305219c
lib/codeql/rust/elements/FormatArgsExpr.qll f2ffad5a1105b29a8437c8ed6cf918cfcf4d65ac164bbf1be0585c3b673ca749 3ba20dc312a0a994bb43b37b2db72cbd4e06061b97918fa0e84ce355070ffbeb
lib/codeql/rust/elements/FormatArgument.qll bdd93e1da78637f19beee6f953d3a45512100e925d90cb5ad08a097f412009b8 2a0ae7eb885615e380f925c0d130a1b795bf3c395486550a1f1c9c82848f8d77
lib/codeql/rust/elements/FormatArgsExpr.qll 8127cbe4082f7acc3d8a05298c2c9bea302519b8a6cd2d158a83c516d18fc487 88cf9b3bedd69a1150968f9a465c904bbb6805da0e0b90cfd1fc0dab1f6d9319
lib/codeql/rust/elements/FormatArgument.qll f6fe17ee1481c353dd42edae8b5fa79aeb99dff25b4842ec9a6f267b1837d1e3 5aed19c2daf2383b89ad7fd527375641cff26ddee7afddb89bc0d18d520f4034
lib/codeql/rust/elements/FormatTemplateVariableAccess.qll ff3218a1dda30c232d0ecd9d1c60bbb9f3973456ef0bee1d1a12ad14b1e082b5 e4316291c939800d8b34d477d92be9404a30d52b7eee37302aef3d3205cf4ae0
lib/codeql/rust/elements/Function.qll 2c76c2c7036891996b1f0ebde16c414edf37ebb44ff9c3483088dc6218733e07 d84d017d98aa240bf3bee6502a030aa8cfb7ed95425ffa9853e73b41485e1f4a
lib/codeql/rust/elements/GenericArg.qll 5f11ce0e3c5f08de84db61f56ba1b984652455ba6b95a8b8a5b5a235913d4072 756b6a73d66fde45bdcc65ce2362a5b1391af2927e6d54b6550b3ecd5fd11e75
@@ -452,10 +452,10 @@ lib/codeql/rust/elements/internal/generated/FieldList.qll 43c13c6e3c9ba75a7a4cb8
lib/codeql/rust/elements/internal/generated/FnPtrType.qll 748d766dbefd19a7d644734c57885eeede66897029bbfe1b87919517f43bfde2 5a7d80acc00e56594ed85026a8ea4923104d2e98c2e42db8c5bcd32ddd164e48
lib/codeql/rust/elements/internal/generated/ForExpr.qll d81751e9599874a1292a0aace80b2de60ab36fc43f74ec08fbdfe044fc19e5c1 34a64586f8ffbadd44d0e747f69ab550a16149b658a9c92d9593689cb9a4f6fc
lib/codeql/rust/elements/internal/generated/ForType.qll 3d43d044a1189281f09c55caafb6c8020a836f49e2866077086101925a573cf2 646b59bfd1b428aaf7211f574c49f79cb4c6a79ca151aa0663b2b31480298721
lib/codeql/rust/elements/internal/generated/Format.qll 37ad20cf2bf363b4027a8913d095292c8a4eb8ccdf2a9965f2fb7d41930f9bfe 329b89cdd75ce951269273dd18897e32ff5cfcc94f451001c64143386c1e48dd
lib/codeql/rust/elements/internal/generated/Format.qll df7ef61e6ba61fa0eb093f8e6b3e7a0329104e03f659c9507db9535b8b4ea759 ef8ddd98405fc84938ad8cd5f87d2858e01d06a6bb00566a785a984b60a79dc6
lib/codeql/rust/elements/internal/generated/FormatArgsArg.qll e07a1ae310f590003f1b88fada7dcf4847c99adb9d4c838d1c88e66e1da85c5f 0ef7342451fe2cb06e765fb4b33bb8c4a9b927f5edbc8feb5c6ba3655697f447
lib/codeql/rust/elements/internal/generated/FormatArgsExpr.qll 40d6daa7d2bafb33798a21d79774dc802cfbd7a31618ac3bd0149399ea2bf893 d1172e2151791228559004792e125fc4625f6a26ffad25f29efb0ad263bf8795
lib/codeql/rust/elements/internal/generated/FormatArgument.qll 00646f38217a66978b8b2648cca39dddbed22ece693b26cb682f019fbfedda95 e364e085f967847a7ed21b76156a9203d64032f0f0eea357b4779885a41bf9a7
lib/codeql/rust/elements/internal/generated/FormatArgsExpr.qll 8aed8715a27d3af3de56ded4610c6792a25216b1544eb7e57c8b0b37c14bd9c1 590a2b0063d2ecd00bbbd1ce29603c8fd69972e34e6daddf309c915ce4ec1375
lib/codeql/rust/elements/internal/generated/FormatArgument.qll cd05153276e63e689c95d5537fbc7d892615f62e110323759ef02e23a7587407 be2a4531b498f01625effa4c631d51ee8857698b00cfb829074120a0f2696d57
lib/codeql/rust/elements/internal/generated/FormatTemplateVariableAccess.qll a6175214fad445df9234b3ee9bf5147da75baf82473fb8d384b455e3add0dac1 a928db0ff126b2e54a18f5c488232abd1bd6c5eda24591d3c3bb80c6ee71c770
lib/codeql/rust/elements/internal/generated/Function.qll f285ee0c771f897eba6db34a7e98f3cfb7db91b0df252ff4b37fc9d779de0bfb 07401e832565ff376acda219514c2e2bbe4ae5058c76a73b40ca6ca66f1626c7
lib/codeql/rust/elements/internal/generated/GenericArg.qll 464da0ba1c5ddcd1be68617167f177773d99b5ac4775ec8ea24d503e789a9099 6faa1033d59baf7c210ac4837a55781cfc054b7acbad8027faf4630dbfa6e101
@@ -509,7 +509,7 @@ lib/codeql/rust/elements/internal/generated/ParamList.qll c808c9d84dd7800573832b
lib/codeql/rust/elements/internal/generated/ParenExpr.qll bc0731505bfe88516205ec360582a4222d2681d11342c93e15258590ddee82f2 d4bd6e0c80cf1d63746c88d4bcb3a01d4c75732e5da09e3ebd9437ced227fb60
lib/codeql/rust/elements/internal/generated/ParenPat.qll ce24b8f8ecbf0f204af200317405724063887257460c80cf250c39b2fdf37185 e7c87d37e1a0ca7ea03840017e1aa9ddb7f927f1f3b6396c0305b46aeee33db6
lib/codeql/rust/elements/internal/generated/ParenType.qll 9cc954d73f8330dcac7b475f97748b63af5c8766dee9d2f2872c0a7e4c903537 c07534c8a9c683c4a9b11d490095647e420de0a0bfc23273eaf6f31b00244273
lib/codeql/rust/elements/internal/generated/ParentChild.qll 2237ba700c7d790cbbf7ad4d86889d22c6d210af62474ad8d363d79abb574722 36f9d47b002a241f0f793816ca9e6327fbbefb02268665553c56ded6012f82ec
lib/codeql/rust/elements/internal/generated/ParentChild.qll 52186ab2aead10bbbaab401272afff0b8247b0050064123d0e45d972ec501dee f082318c0da678845763d6070283872b94b59425fbaa305582b5fe72da03e7e6
lib/codeql/rust/elements/internal/generated/Pat.qll 3605ac062be2f294ee73336e9669027b8b655f4ad55660e1eab35266275154ee 7f9400db2884d336dd1d21df2a8093759c2a110be9bf6482ce8e80ae0fd74ed4
lib/codeql/rust/elements/internal/generated/Path.qll 4c1c8e840ed57880e574142b081b11d7a7428a009f10e3aa8f4645e211f6b2e0 989668cf0f1bdee7557e2f97c01e41d2a56848227fed41477833f5fc1e1d35f6
lib/codeql/rust/elements/internal/generated/PathExpr.qll 2096e3c1db22ee488a761690adabfc9cfdea501c99f7c5d96c0019cb113fc506 54245ce0449c4e263173213df01e079d5168a758503a5dbd61b25ad35a311140
@@ -522,7 +522,7 @@ lib/codeql/rust/elements/internal/generated/PtrType.qll 40099c5a4041314b66932dfd
lib/codeql/rust/elements/internal/generated/PureSynthConstructors.qll ea294a3ba33fd1bc632046c4fedbcb84dcb961a8e4599969d65893b19d90e590 ea294a3ba33fd1bc632046c4fedbcb84dcb961a8e4599969d65893b19d90e590
lib/codeql/rust/elements/internal/generated/RangeExpr.qll 23cca03bf43535f33b22a38894f70d669787be4e4f5b8fe5c8f7b964d30e9027 18624cef6c6b679eeace2a98737e472432e0ead354cca02192b4d45330f047c9
lib/codeql/rust/elements/internal/generated/RangePat.qll efd93730de217cf50dcba5875595263a5eadf9f7e4e1272401342a094d158614 229b251b3d118932e31e78ac4dfb75f48b766f240f20d436062785606d44467b
lib/codeql/rust/elements/internal/generated/Raw.qll b534b0f2318a3a15d27cfa1d2d98ad4ef778b48edf2d36b49c56cf350a0f8328 baf18167656d407fc496ed222fcc9766030b018651f8bc4e2801a1ccbbfb29d6
lib/codeql/rust/elements/internal/generated/Raw.qll b23d3574920376ca7c52858d6ad2ea6670640812422329f9c44f699075c16d89 13c1a199de3e71f012bdab0fa2b982f1c92f95536b07bbbe816e680a0e64ad71
lib/codeql/rust/elements/internal/generated/RecordExpr.qll eb6cb662e463f9260efae1a6ce874fa781172063b916ef1963f861e9942d308d 1a21cbccc8f3799ff13281e822818ebfb21d81591720a427cac3625512cb9d40
lib/codeql/rust/elements/internal/generated/RecordExprField.qll 7e9f8663d3b74ebbc9603b10c9912f082febba6bd73d344b100bbd3edf837802 fbe6b578e7fd5d5a6f21bbb8c388957ab7210a6a249ec71510a50fb35b319ea1
lib/codeql/rust/elements/internal/generated/RecordExprFieldList.qll 179a97211fe7aa6265085d4d54115cdbc0e1cd7c9b2135591e8f36d6432f13d3 dd44bbbc1e83a1ed3a587afb729d7debf7aeb7b63245de181726af13090e50c0
@@ -712,13 +712,19 @@ test/extractor-tests/generated/ForExpr/ForExpr_getPat.ql 1e0205a9b3a58fd2ddba49e
test/extractor-tests/generated/ForType/ForType.ql ba930d0c4fe52d57449ce4025b1c3e49c688afc5ef18ee8ac1ed7a9fd3eb8d41 08e9aa0301a942f6f9564ddeddc69606f3e2916e1b551cc56ae3b6048c56ce61
test/extractor-tests/generated/ForType/ForType_getGenericParamList.ql e25cd79737bbae92d8f417c6bbf6fb8ae660976b8005cd91d0900c7076fdd827 b1e32b7e3ca9f29a4564f83e37ae53de6baf04837a393e6dedc64a01cc7d10e8
test/extractor-tests/generated/ForType/ForType_getTy.ql e932d3412828bb83afc42e2dc1a4cbe9fcf25ec9a9617ec138722f834091a61a 298fc9df34b2cb436c8f180c4d229341ee4a73e3c451b905f017f32a6f65056c
test/extractor-tests/generated/FormatArgsArg/FormatArgsArg.ql a521903c73f79e2616f7b8ef76790e11cbf432f8437825d52d117da232022b9e 4cb195d09ecb51e5bbd5c1c069ec1720f74fc074efc88b0f5c07cfc140167775
test/extractor-tests/generated/FormatArgsArg/FormatArgsArg_getExpr.ql 7e1a7f902fb661660760d2a2f3f4cb6818a0c9f5b5061ede6ae80223774e4e09 8a50f64cba6f56320631206c801160201e3c98e74367bb035d689baaa9b4e411
test/extractor-tests/generated/FormatArgsArg/FormatArgsArg_getName.ql 0e2f24388d516e14d195957163a2d5d97029c9e11a83ca71cf69e00ecc0bb2a8 dab2969f5ae6a15ec331c0152e7c116d1ee2c3d073b2d4da59ffbcb83404c65f
test/extractor-tests/generated/FormatArgsExpr/FormatArgsExpr.ql 0cd439f61569ecf046e9548c458329647f331bfa034ae8b3d4f7628595881287 013a948607e1ac96100ea9a8cd3c8f357e378ac21baa015dcf4927022c2bdafb
test/extractor-tests/generated/FormatArgsExpr/Format.ql 25268dd7ad2a58b071c3a38164944c1b7389dfdda01c99ef2694a475596341b4 0a3f674d5a4f005835b9a5ba11a6e8bf58477829258f30ae7d8f76f8986f7b7f
test/extractor-tests/generated/FormatArgsExpr/FormatArgsArg.ql a521903c73f79e2616f7b8ef76790e11cbf432f8437825d52d117da232022b9e 4cb195d09ecb51e5bbd5c1c069ec1720f74fc074efc88b0f5c07cfc140167775
test/extractor-tests/generated/FormatArgsExpr/FormatArgsArg_getExpr.ql 7e1a7f902fb661660760d2a2f3f4cb6818a0c9f5b5061ede6ae80223774e4e09 8a50f64cba6f56320631206c801160201e3c98e74367bb035d689baaa9b4e411
test/extractor-tests/generated/FormatArgsExpr/FormatArgsArg_getName.ql 0e2f24388d516e14d195957163a2d5d97029c9e11a83ca71cf69e00ecc0bb2a8 dab2969f5ae6a15ec331c0152e7c116d1ee2c3d073b2d4da59ffbcb83404c65f
test/extractor-tests/generated/FormatArgsExpr/FormatArgsExpr.ql 7b6f09b23d0dffa19b8dddf7f5cfe53068f8a8e5279e235c6d54e60616bd0822 47db74f035770ce708a00355acbfd4ae99152b7eb29cf28001985806a4efe5aa
test/extractor-tests/generated/FormatArgsExpr/FormatArgsExpr_getArg.ql 8f692486be1546b914b17abdff4a989dfbaa889bfa1fc44597f4357806c1a1dd da9fd237e31e9c8dd0ef0c3c968157815b87d3e8dcdfd74674c988ce2ab6d270
test/extractor-tests/generated/FormatArgsExpr/FormatArgsExpr_getAttr.ql 1f9bf1344f942e65c3a3591b6ae04d3f5a2a1a65459bce0d976698de7d8a5958 02acb861d8ab4d32cf144c589881a888c3da5e2ade27e8c85fec3ae45219bb3b
test/extractor-tests/generated/FormatArgsExpr/FormatArgsExpr_getFormat.ql 02d3fad540700966488b24c62dcf200548154a2f10f578ee2995d8c4ebe32287 cccfe779b9804c2bb968a2b1f54da8a72393805c2c8b31d7160e8538f2f335f2
test/extractor-tests/generated/FormatArgsExpr/FormatArgsExpr_getTemplate.ql c912ac37275cbe7b3b29607bed1a3190c80779436422c14a475113e1bfd91a54 ef90f67a9b952a38ce557b1afbf0b5ce8551e83ddfaad8309a0c9523e40b5ea7
test/extractor-tests/generated/FormatArgsExpr/FormatArgument.ql 7a7ee3a3322b4af8cb3b525cfed8cc9719d136ea80aa6b3fb30c7e16394dd93f 5aa8a77d7741b02f8ceb9e5991efa4c2c43c6f1624989218990e985108dae535
test/extractor-tests/generated/FormatArgsExpr/FormatArgument_getVariable.ql 7bd4ec3dde2ef0463585794101e6cc426c368b0e4ab95fbb1f24f8f0a76cf471 e7b01e8b21df5b22c51643e2c909c6fc4ca96fda41b3290c907ba228abe8669b
test/extractor-tests/generated/FormatArgsExpr/FormatTemplateVariableAccess.ql 2793ba1ff52182dab992d82d3767a000928f6b2fbfdb621349cafc183f0d2480 c3777d03214f7feb9020de3ce45af6556129e39e9b30d083de605b70ab9a0a12
test/extractor-tests/generated/FormatArgsExpr/Format_getArgument.ql 26d592398a17795427b5b6b51ff4a013ee15c31443e732a000baca5f2e65acca 7940a864b84b89e84d7fb186599cb8b6bcbead7141c592b8ab0c59fcd380d5fb
test/extractor-tests/generated/Function/Function.ql c1c2a9b68c35f839ccd2b5e62e87d1acd94dcc2a3dc4c307c269b84b2a0806e6 1c446f19d2f81dd139aa5a1578d1b165e13bddbaeab8cfee8f0430bced3a99ab
test/extractor-tests/generated/Function/Function_getAbi.ql e5c9c97de036ddd51cae5d99d41847c35c6b2eabbbd145f4467cb501edc606d8 0b81511528bd0ef9e63b19edfc3cb638d8af43eb87d018fad69d6ef8f8221454
test/extractor-tests/generated/Function/Function_getAttr.ql 44067ee11bdec8e91774ff10de0704a8c5c1b60816d587378e86bf3d82e1f660 b4bebf9441bda1f2d1e34e9261e07a7468cbabf53cf8047384f3c8b11869f04e

12
rust/ql/.gitattributes generated vendored
View File

@@ -714,13 +714,19 @@
/test/extractor-tests/generated/ForType/ForType.ql linguist-generated
/test/extractor-tests/generated/ForType/ForType_getGenericParamList.ql linguist-generated
/test/extractor-tests/generated/ForType/ForType_getTy.ql linguist-generated
/test/extractor-tests/generated/FormatArgsArg/FormatArgsArg.ql linguist-generated
/test/extractor-tests/generated/FormatArgsArg/FormatArgsArg_getExpr.ql linguist-generated
/test/extractor-tests/generated/FormatArgsArg/FormatArgsArg_getName.ql linguist-generated
/test/extractor-tests/generated/FormatArgsExpr/Format.ql linguist-generated
/test/extractor-tests/generated/FormatArgsExpr/FormatArgsArg.ql linguist-generated
/test/extractor-tests/generated/FormatArgsExpr/FormatArgsArg_getExpr.ql linguist-generated
/test/extractor-tests/generated/FormatArgsExpr/FormatArgsArg_getName.ql linguist-generated
/test/extractor-tests/generated/FormatArgsExpr/FormatArgsExpr.ql linguist-generated
/test/extractor-tests/generated/FormatArgsExpr/FormatArgsExpr_getArg.ql linguist-generated
/test/extractor-tests/generated/FormatArgsExpr/FormatArgsExpr_getAttr.ql linguist-generated
/test/extractor-tests/generated/FormatArgsExpr/FormatArgsExpr_getFormat.ql linguist-generated
/test/extractor-tests/generated/FormatArgsExpr/FormatArgsExpr_getTemplate.ql linguist-generated
/test/extractor-tests/generated/FormatArgsExpr/FormatArgument.ql linguist-generated
/test/extractor-tests/generated/FormatArgsExpr/FormatArgument_getVariable.ql linguist-generated
/test/extractor-tests/generated/FormatArgsExpr/FormatTemplateVariableAccess.ql linguist-generated
/test/extractor-tests/generated/FormatArgsExpr/Format_getArgument.ql linguist-generated
/test/extractor-tests/generated/Function/Function.ql linguist-generated
/test/extractor-tests/generated/Function/Function_getAbi.ql linguist-generated
/test/extractor-tests/generated/Function/Function_getAttr.ql linguist-generated

View File

@@ -0,0 +1,116 @@
/**
* Provides abstract classes representing generic concepts such as file system
* access or system command execution, for which individual framework libraries
* provide concrete subclasses.
*/
private import codeql.rust.dataflow.DataFlow
private import codeql.threatmodels.ThreatModels
/**
* A data flow source for a specific threat-model.
*
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `ThreatModelSource::Range` instead.
*/
final class ThreatModelSource = ThreatModelSource::Range;
/**
* Provides a class for modeling new sources for specific threat-models.
*/
module ThreatModelSource {
/**
* A data flow source, for a specific threat-model.
*/
abstract class Range extends DataFlow::Node {
/**
* Gets a string that represents the source kind with respect to threat modeling.
*
* See
* - https://github.com/github/codeql/blob/main/docs/codeql/reusables/threat-model-description.rst
* - https://github.com/github/codeql/blob/main/shared/threat-models/ext/threat-model-grouping.model.yml
*/
abstract string getThreatModel();
/**
* Gets a string that describes the type of this threat-model source.
*/
abstract string getSourceType();
}
}
/**
* A data flow source that is enabled in the current threat model configuration.
*/
class ActiveThreatModelSource extends ThreatModelSource {
ActiveThreatModelSource() { currentThreatModel(this.getThreatModel()) }
}
/**
* A data-flow node that constructs a SQL statement.
*
* Often, it is worthy of an alert if a SQL statement is constructed such that
* executing it would be a security risk.
*
* If it is important that the SQL statement is executed, use `SqlExecution`.
*
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `SqlConstruction::Range` instead.
*/
final class SqlConstruction = SqlConstruction::Range;
/**
* Provides a class for modeling new SQL execution APIs.
*/
module SqlConstruction {
/**
* A data-flow node that constructs a SQL statement.
*/
abstract class Range extends DataFlow::Node {
/**
* Gets the argument that specifies the SQL statements to be constructed.
*/
abstract DataFlow::Node getSql();
}
}
/**
* A data-flow node that executes SQL statements.
*
* If the context of interest is such that merely constructing a SQL statement
* would be valuable to report, consider using `SqlConstruction`.
*
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `SqlExecution::Range` instead.
*/
final class SqlExecution = SqlExecution::Range;
/**
* Provides a class for modeling new SQL execution APIs.
*/
module SqlExecution {
/**
* A data-flow node that executes SQL statements.
*/
abstract class Range extends DataFlow::Node {
/**
* Gets the argument that specifies the SQL statements to be executed.
*/
abstract DataFlow::Node getSql();
}
}
/**
* A data-flow node that performs SQL sanitization.
*/
final class SqlSanitization = SqlSanitization::Range;
/**
* Provides a class for modeling new SQL sanitization APIs.
*/
module SqlSanitization {
/**
* A data-flow node that performs SQL sanitization.
*/
abstract class Range extends DataFlow::Node { }
}

View File

@@ -13,6 +13,8 @@ class AstCfgNode = CfgImpl::AstCfgNode;
class ExitCfgNode = CfgImpl::ExitNode;
class AnnotatedExitCfgNode = CfgImpl::AnnotatedExitNode;
/**
* An assignment expression, for example
*

View File

@@ -894,7 +894,11 @@ module MakeCfgNodes<LocationSig Loc, InputSig<Loc> Input> {
/**
* A FormatArgsExpr. For example:
* ```rust
* todo!()
* format_args!("no args");
* format_args!("{} foo {:?}", 1, 2);
* format_args!("{b} foo {a:?}", a=1, b=2);
* let (x, y) = (1, 42);
* format_args!("{x}, {y}");
* ```
*/
final class FormatArgsExprCfgNode extends CfgNodeFinal, ExprCfgNode {
@@ -946,6 +950,21 @@ module MakeCfgNodes<LocationSig Loc, InputSig<Loc> Input> {
* Holds if `getTemplate()` exists.
*/
predicate hasTemplate() { exists(this.getTemplate()) }
/**
* Gets the `index`th format of this format arguments expression (0-based).
*/
Format getFormat(int index) { result = node.getFormat(index) }
/**
* Gets any of the formats of this format arguments expression.
*/
Format getAFormat() { result = this.getFormat(_) }
/**
* Gets the number of formats of this format arguments expression.
*/
int getNumberOfFormats() { result = count(int i | exists(this.getFormat(i))) }
}
final private class ParentFormatTemplateVariableAccess extends ParentAstNode,

View File

@@ -43,22 +43,59 @@ final class DataFlowCallable extends TDataFlowCallable {
}
final class DataFlowCall extends TDataFlowCall {
private CallExprBaseCfgNode call;
DataFlowCall() { this = TCall(call) }
/** Gets the underlying call in the CFG, if any. */
CallExprCfgNode asCallExprCfgNode() { this = TNormalCall(result) }
CallExprCfgNode asCallExprCfgNode() { result = call }
MethodCallExprCfgNode asMethodCallExprCfgNode() { this = TMethodCall(result) }
MethodCallExprCfgNode asMethodCallExprCfgNode() { result = call }
CallExprBaseCfgNode asExprCfgNode() {
result = this.asCallExprCfgNode() or result = this.asMethodCallExprCfgNode()
}
CallExprBaseCfgNode asCallBaseExprCfgNode() { result = call }
DataFlowCallable getEnclosingCallable() {
result = TCfgScope(this.asExprCfgNode().getExpr().getEnclosingCfgScope())
result = TCfgScope(call.getExpr().getEnclosingCfgScope())
}
string toString() { result = this.asExprCfgNode().toString() }
string toString() { result = this.asCallBaseExprCfgNode().toString() }
Location getLocation() { result = this.asExprCfgNode().getLocation() }
Location getLocation() { result = this.asCallBaseExprCfgNode().getLocation() }
}
/**
* The position of a parameter or an argument in a function or call.
*
* As there is a 1-to-1 correspondence between parameter positions and
* arguments positions in Rust we use the same type for both.
*/
final class ParameterPosition extends TParameterPosition {
/** Gets the underlying integer position, if any. */
int getPosition() { this = TPositionalParameterPosition(result) }
/** Holds if this position represents the `self` position. */
predicate isSelf() { this = TSelfParameterPosition() }
/** Gets a textual representation of this position. */
string toString() {
result = this.getPosition().toString()
or
result = "self" and this.isSelf()
}
AstNode getParameterIn(ParamList ps) {
result = ps.getParam(this.getPosition())
or
result = ps.getSelfParam() and this.isSelf()
}
}
/** Holds if `arg` is an argument of `call` at the position `pos`. */
private predicate isArgumentForCall(ExprCfgNode arg, CallExprBaseCfgNode call, ParameterPosition pos) {
arg = call.getArgument(pos.getPosition())
or
// The self argument in a method call.
arg = call.(MethodCallExprCfgNode).getReceiver() and pos.isSelf()
}
module Node {
@@ -93,11 +130,6 @@ module Node {
* Gets this node's underlying SSA definition, if any.
*/
Ssa::Definition asDefinition() { none() }
/**
* Gets the parameter that corresponds to this node, if any.
*/
Param asParameter() { none() }
}
/** A node type that is not implemented. */
@@ -111,7 +143,7 @@ module Node {
override Location getLocation() { none() }
}
/** A data flow node that corresponds to a CFG node for an AST node. */
/** A data flow node that corresponds directly to a CFG node for an AST node. */
abstract class AstCfgFlowNode extends Node {
AstCfgNode n;
@@ -145,24 +177,37 @@ module Node {
PatNode() { this = TPatNode(n) }
/** Gets the `Pat` in the AST that this node corresponds to. */
Pat getPat() { result = n.getPat() }
/** Gets the `PatCfgNode` in the CFG that this node corresponds to. */
PatCfgNode getPat() { result = n }
}
abstract class ParameterNode extends AstCfgFlowNode { }
/**
* The value of a parameter at function entry, viewed as a node in a data
* flow graph.
*/
final class ParameterNode extends AstCfgFlowNode, TParameterNode {
final class PositionalParameterNode extends ParameterNode, TParameterNode {
override ParamCfgNode n;
ParameterNode() { this = TParameterNode(n) }
PositionalParameterNode() { this = TParameterNode(n) }
/** Gets the parameter in the CFG that this node corresponds to. */
ParamCfgNode getParameter() { result = n }
}
final class ArgumentNode = NaNode;
final class SelfParameterNode extends ParameterNode, TSelfParameterNode {
override SelfParamCfgNode n;
SelfParameterNode() { this = TSelfParameterNode(n) }
/** Gets the self parameter in the AST that this node corresponds to. */
SelfParamCfgNode getSelfParameter() { result = n }
}
final class ArgumentNode extends ExprNode {
ArgumentNode() { isArgumentForCall(n, _, _) }
}
/** An SSA node. */
class SsaNode extends Node, TSsaNode {
@@ -185,7 +230,7 @@ module Node {
/** A data flow node that represents a value returned by a callable. */
final class ReturnNode extends ExprNode {
ReturnNode() { this.getCfgNode().getASuccessor() instanceof ExitCfgNode }
ReturnNode() { this.getCfgNode().getASuccessor() instanceof AnnotatedExitCfgNode }
ReturnKind getKind() { any() }
}
@@ -197,10 +242,10 @@ module Node {
}
final private class ExprOutNode extends ExprNode, OutNode {
ExprOutNode() { this.asExpr() instanceof CallExprCfgNode }
ExprOutNode() { this.asExpr() instanceof CallExprBaseCfgNode }
/** Gets the underlying call CFG node that includes this out node. */
override DataFlowCall getCall() { result.asExprCfgNode() = this.getCfgNode() }
override DataFlowCall getCall() { result.asCallBaseExprCfgNode() = this.getCfgNode() }
}
/**
@@ -214,9 +259,19 @@ module Node {
* Nodes corresponding to AST elements, for example `ExprNode`, usually refer
* to the value before the update.
*/
final class PostUpdateNode extends Node::NaNode {
final class PostUpdateNode extends Node, TArgumentPostUpdateNode {
private ExprCfgNode n;
PostUpdateNode() { this = TArgumentPostUpdateNode(n) }
/** Gets the node before the state update. */
Node getPreUpdateNode() { none() }
Node getPreUpdateNode() { result = TExprNode(n) }
final override CfgScope getCfgScope() { result = n.getScope() }
final override Location getLocation() { result = n.getLocation() }
final override string toString() { result = n.toString() }
}
final class CastNode = NaNode;
@@ -226,25 +281,27 @@ final class Node = Node::Node;
/** Provides logic related to SSA. */
module SsaFlow {
private module Impl = SsaImpl::DataFlowIntegration;
private module SsaFlow = SsaImpl::DataFlowIntegration;
private Node::ParameterNode toParameterNode(ParamCfgNode p) { result.getParameter() = p }
private Node::ParameterNode toParameterNode(ParamCfgNode p) {
result.(Node::PositionalParameterNode).getParameter() = p
}
/** Converts a control flow node into an SSA control flow node. */
Impl::Node asNode(Node n) {
SsaFlow::Node asNode(Node n) {
n = TSsaNode(result)
or
result.(Impl::ExprNode).getExpr() = n.asExpr()
result.(SsaFlow::ExprNode).getExpr() = n.asExpr()
or
n = toParameterNode(result.(Impl::ParameterNode).getParameter())
n = toParameterNode(result.(SsaFlow::ParameterNode).getParameter())
}
predicate localFlowStep(SsaImpl::DefinitionExt def, Node nodeFrom, Node nodeTo, boolean isUseStep) {
Impl::localFlowStep(def, asNode(nodeFrom), asNode(nodeTo), isUseStep)
SsaFlow::localFlowStep(def, asNode(nodeFrom), asNode(nodeTo), isUseStep)
}
predicate localMustFlowStep(SsaImpl::DefinitionExt def, Node nodeFrom, Node nodeTo) {
Impl::localMustFlowStep(def, asNode(nodeFrom), asNode(nodeTo))
SsaFlow::localMustFlowStep(def, asNode(nodeFrom), asNode(nodeTo))
}
}
@@ -276,6 +333,9 @@ module LocalFlow {
nodeFrom.(Node::AstCfgFlowNode).getCfgNode() =
nodeTo.(Node::SsaNode).getDefinitionExt().(Ssa::WriteDefinition).getControlFlowNode()
or
nodeFrom.(Node::PositionalParameterNode).getParameter().getPat() =
nodeTo.(Node::PatNode).getPat()
or
SsaFlow::localFlowStep(_, nodeFrom, nodeTo, _)
or
exists(AssignmentExprCfgNode a |
@@ -291,6 +351,8 @@ private class ReturnKindAlias = ReturnKind;
private class DataFlowCallAlias = DataFlowCall;
private class ParameterPositionAlias = ParameterPosition;
module RustDataFlow implements InputSig<Location> {
/**
* An element, viewed as a node in a data flow graph. Either an expression
@@ -310,9 +372,15 @@ module RustDataFlow implements InputSig<Location> {
final class CastNode = Node::NaNode;
predicate isParameterNode(ParameterNode p, DataFlowCallable c, ParameterPosition pos) { none() }
/** Holds if `p` is a parameter of `c` at the position `pos`. */
predicate isParameterNode(ParameterNode p, DataFlowCallable c, ParameterPosition pos) {
p.getCfgNode().getAstNode() = pos.getParameterIn(c.asCfgScope().(Callable).getParamList())
}
predicate isArgumentNode(ArgumentNode n, DataFlowCall call, ArgumentPosition pos) { none() }
/** Holds if `n` is an argument of `c` at the position `pos`. */
predicate isArgumentNode(ArgumentNode n, DataFlowCall call, ArgumentPosition pos) {
isArgumentForCall(n.getCfgNode(), call.asCallBaseExprCfgNode(), pos)
}
DataFlowCallable nodeGetEnclosingCallable(Node node) { result = node.getEnclosingCallable() }
@@ -335,10 +403,9 @@ module RustDataFlow implements InputSig<Location> {
DataFlowCallable viableCallable(DataFlowCall c) {
exists(Function f, string name | result.asCfgScope() = f and name = f.getName().toString() |
if f.getParamList().hasSelfParam()
then name = c.asMethodCallExprCfgNode().getMethodCallExpr().getNameRef().getText()
then name = c.asMethodCallExprCfgNode().getNameRef().getText()
else
name =
c.asCallExprCfgNode().getCallExpr().getExpr().(PathExpr).getPath().getPart().toString()
name = c.asCallExprCfgNode().getExpr().getExpr().(PathExpr).getPath().getPart().toString()
)
}
@@ -377,19 +444,15 @@ module RustDataFlow implements InputSig<Location> {
ContentApprox getContentApprox(Content c) { any() }
class ParameterPosition extends string {
ParameterPosition() { this = "pos" }
}
class ParameterPosition = ParameterPositionAlias;
class ArgumentPosition extends string {
ArgumentPosition() { this = "pos" }
}
class ArgumentPosition = ParameterPosition;
/**
* Holds if the parameter position `ppos` matches the argument position
* `apos`.
*/
predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) { none() }
predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) { ppos = apos }
/**
* Holds if there is a simple local flow step from `node1` to `node2`. These
@@ -497,13 +560,13 @@ private module Cached {
newtype TNode =
TExprNode(ExprCfgNode n) or
TParameterNode(ParamCfgNode p) or
TSelfParameterNode(SelfParamCfgNode p) or
TPatNode(PatCfgNode p) or
TArgumentPostUpdateNode(ExprCfgNode e) { isArgumentForCall(e, _, _) } or
TSsaNode(SsaImpl::DataFlowIntegration::SsaNode node)
cached
newtype TDataFlowCall =
TNormalCall(CallExprCfgNode c) or
TMethodCall(MethodCallExprCfgNode c)
newtype TDataFlowCall = TCall(CallExprBaseCfgNode c)
cached
newtype TOptionalContentSet =
@@ -521,6 +584,13 @@ private module Cached {
predicate localFlowStepImpl(Node::Node nodeFrom, Node::Node nodeTo) {
LocalFlow::localFlowStepCommon(nodeFrom, nodeTo)
}
cached
newtype TParameterPosition =
TPositionalParameterPosition(int i) {
i in [0 .. max([any(ParamList l).getNumberOfParams(), any(ArgList l).getNumberOfArgs()]) - 1]
} or
TSelfParameterPosition()
}
import Cached

View File

@@ -5,6 +5,7 @@
private import internal.FormatImpl
import codeql.rust.elements.FormatArgsExpr
import codeql.rust.elements.FormatArgument
import codeql.rust.elements.Locatable
/**

View File

@@ -6,12 +6,17 @@
private import internal.FormatArgsExprImpl
import codeql.rust.elements.Attr
import codeql.rust.elements.Expr
import codeql.rust.elements.Format
import codeql.rust.elements.FormatArgsArg
/**
* A FormatArgsExpr. For example:
* ```rust
* todo!()
* format_args!("no args");
* format_args!("{} foo {:?}", 1, 2);
* format_args!("{b} foo {a:?}", a=1, b=2);
* let (x, y) = (1, 42);
* format_args!("{x}, {y}");
* ```
*/
final class FormatArgsExpr = Impl::FormatArgsExpr;

View File

@@ -5,6 +5,7 @@
private import internal.FormatArgumentImpl
import codeql.rust.elements.Format
import codeql.rust.elements.FormatTemplateVariableAccess
import codeql.rust.elements.Locatable
/**

View File

@@ -16,14 +16,15 @@ module Impl {
/**
* A FormatArgsExpr. For example:
* ```rust
* todo!()
* format_args!("no args");
* format_args!("{} foo {:?}", 1, 2);
* format_args!("{b} foo {a:?}", a=1, b=2);
* let (x, y) = (1, 42);
* format_args!("{x}, {y}");
* ```
*/
class FormatArgsExpr extends Generated::FormatArgsExpr {
/**
* Gets the `index`th format of this `FormatArgsExpr`'s formatting template (0-based).
*/
Format getFormat(int index) {
override Format getFormat(int index) {
result =
rank[index + 1](Format f, int i | f.getParent() = this and f.getIndex() = i | f order by i)
}

View File

@@ -39,6 +39,8 @@ module Impl {
override string toString() { result = name }
override Format getParent() { result = Synth::TFormat(parent, index, _, _) }
override FormatTemplateVariableAccess getVariable() { result.getArgument() = this }
}
private class FormatSynthLocationImpl extends FormatArgument, LocatableImpl::SynthLocatable {

View File

@@ -38,6 +38,8 @@ module Impl {
override int getIndex() { result = index }
override FormatArgument getArgument() { result.getParent() = this }
/**
* Gets the name or position reference of this format, if any. For example `name` and `0` in:
* ```rust

View File

@@ -7,6 +7,7 @@
private import codeql.rust.elements.internal.generated.Synth
private import codeql.rust.elements.internal.generated.Raw
import codeql.rust.elements.FormatArgsExpr
import codeql.rust.elements.FormatArgument
import codeql.rust.elements.internal.LocatableImpl::Impl as LocatableImpl
/**
@@ -34,5 +35,15 @@ module Generated {
* Gets the index of this format.
*/
int getIndex() { none() }
/**
* Gets the argument of this format, if it exists.
*/
FormatArgument getArgument() { none() }
/**
* Holds if `getArgument()` exists.
*/
final predicate hasArgument() { exists(this.getArgument()) }
}
}

View File

@@ -9,6 +9,7 @@ private import codeql.rust.elements.internal.generated.Raw
import codeql.rust.elements.Attr
import codeql.rust.elements.Expr
import codeql.rust.elements.internal.ExprImpl::Impl as ExprImpl
import codeql.rust.elements.Format
import codeql.rust.elements.FormatArgsArg
/**
@@ -19,7 +20,11 @@ module Generated {
/**
* A FormatArgsExpr. For example:
* ```rust
* todo!()
* format_args!("no args");
* format_args!("{} foo {:?}", 1, 2);
* format_args!("{b} foo {a:?}", a=1, b=2);
* let (x, y) = (1, 42);
* format_args!("{x}, {y}");
* ```
* INTERNAL: Do not reference the `Generated::FormatArgsExpr` class directly.
* Use the subclass `FormatArgsExpr`, where the following predicates are available.
@@ -81,5 +86,20 @@ module Generated {
* Holds if `getTemplate()` exists.
*/
final predicate hasTemplate() { exists(this.getTemplate()) }
/**
* Gets the `index`th format of this format arguments expression (0-based).
*/
Format getFormat(int index) { none() }
/**
* Gets any of the formats of this format arguments expression.
*/
final Format getAFormat() { result = this.getFormat(_) }
/**
* Gets the number of formats of this format arguments expression.
*/
final int getNumberOfFormats() { result = count(int i | exists(this.getFormat(i))) }
}
}

View File

@@ -7,6 +7,7 @@
private import codeql.rust.elements.internal.generated.Synth
private import codeql.rust.elements.internal.generated.Raw
import codeql.rust.elements.Format
import codeql.rust.elements.FormatTemplateVariableAccess
import codeql.rust.elements.internal.LocatableImpl::Impl as LocatableImpl
/**
@@ -33,5 +34,15 @@ module Generated {
* Gets the parent of this format argument.
*/
Format getParent() { none() }
/**
* Gets the variable of this format argument, if it exists.
*/
FormatTemplateVariableAccess getVariable() { none() }
/**
* Holds if `getVariable()` exists.
*/
final predicate hasVariable() { exists(this.getVariable()) }
}
}

View File

@@ -52,14 +52,17 @@ private module Impl {
}
private Element getImmediateChildOfFormat(Format e, int index, string partialPredicateCall) {
exists(int b, int bLocatable, int n |
exists(int b, int bLocatable, int n, int nArgument |
b = 0 and
bLocatable = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfLocatable(e, i, _)) | i) and
n = bLocatable and
nArgument = n + 1 and
(
none()
or
result = getImmediateChildOfLocatable(e, index - b, partialPredicateCall)
or
index = n and result = e.getArgument() and partialPredicateCall = "Argument()"
)
)
}
@@ -67,14 +70,17 @@ private module Impl {
private Element getImmediateChildOfFormatArgument(
FormatArgument e, int index, string partialPredicateCall
) {
exists(int b, int bLocatable, int n |
exists(int b, int bLocatable, int n, int nVariable |
b = 0 and
bLocatable = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfLocatable(e, i, _)) | i) and
n = bLocatable and
nVariable = n + 1 and
(
none()
or
result = getImmediateChildOfLocatable(e, index - b, partialPredicateCall)
or
index = n and result = e.getVariable() and partialPredicateCall = "Variable()"
)
)
}
@@ -1709,13 +1715,14 @@ private module Impl {
private Element getImmediateChildOfFormatArgsExpr(
FormatArgsExpr e, int index, string partialPredicateCall
) {
exists(int b, int bExpr, int n, int nArg, int nAttr, int nTemplate |
exists(int b, int bExpr, int n, int nArg, int nAttr, int nTemplate, int nFormat |
b = 0 and
bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and
n = bExpr and
nArg = n + 1 + max(int i | i = -1 or exists(e.getArg(i)) | i) and
nAttr = nArg + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
nTemplate = nAttr + 1 and
nFormat = nTemplate + 1 + max(int i | i = -1 or exists(e.getFormat(i)) | i) and
(
none()
or
@@ -1728,6 +1735,9 @@ private module Impl {
partialPredicateCall = "Attr(" + (index - nArg).toString() + ")"
or
index = nAttr and result = e.getTemplate() and partialPredicateCall = "Template()"
or
result = e.getFormat(index - nTemplate) and
partialPredicateCall = "Format(" + (index - nTemplate).toString() + ")"
)
)
}

View File

@@ -1782,7 +1782,11 @@ module Raw {
* INTERNAL: Do not use.
* A FormatArgsExpr. For example:
* ```rust
* todo!()
* format_args!("no args");
* format_args!("{} foo {:?}", 1, 2);
* format_args!("{b} foo {a:?}", a=1, b=2);
* let (x, y) = (1, 42);
* format_args!("{x}, {y}");
* ```
*/
class FormatArgsExpr extends @format_args_expr, Expr {

View File

@@ -0,0 +1,50 @@
/**
* Provides classes and predicates for reasoning about database
* queries built from user-controlled sources (that is, SQL injection
* vulnerabilities).
*/
import rust
private import codeql.rust.dataflow.DataFlow
private import codeql.rust.Concepts
private import codeql.util.Unit
/**
* Provides default sources, sinks and barriers for detecting SQL injection
* vulnerabilities, as well as extension points for adding your own.
*/
module SqlInjection {
/**
* A data flow source for SQL injection vulnerabilities.
*/
abstract class Source extends DataFlow::Node { }
/**
* A data flow sink for SQL injection vulnerabilities.
*/
abstract class Sink extends DataFlow::Node { }
/**
* A barrier for SQL injection vulnerabilities.
*/
abstract class Barrier extends DataFlow::Node { }
/**
* An active threat-model source, considered as a flow source.
*/
private class ActiveThreatModelSourceAsSource extends Source, ActiveThreatModelSource { }
/**
* A flow sink that is the statement of an SQL construction.
*/
class SqlConstructionAsSink extends Sink {
SqlConstructionAsSink() { this = any(SqlConstruction c).getSql() }
}
/**
* A flow sink that is the statement of an SQL execution.
*/
class SqlExecutionAsSink extends Sink {
SqlExecutionAsSink() { this = any(SqlExecution e).getSql() }
}
}

View File

@@ -8,6 +8,7 @@ dependencies:
codeql/controlflow: ${workspace}
codeql/dataflow: ${workspace}
codeql/regex: ${workspace}
codeql/threat-models: ${workspace}
codeql/mad: ${workspace}
codeql/ssa: ${workspace}
codeql/tutorial: ${workspace}

View File

@@ -0,0 +1,39 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
If a database query (such as an SQL query) is built from user-provided data without sufficient sanitization, a user may be able to run malicious database queries. An attacker can craft the part of the query they control to change the overall meaning of the query.
</p>
</overview>
<recommendation>
<p>
Most database connector libraries offer a way to safely embed untrusted data into a query using query parameters or prepared statements. You should use these features to build queries, rather than string concatenation or similar methods. You can also escape (sanitize) user-controlled strings so that they can be included directly in an SQL command. A library function should be used for escaping, because this approach is only safe if the escaping function is robust against all possible inputs.
</p>
</recommendation>
<example>
<p>
In the following examples, an SQL query is prepared using string formatting to directly include a user-controlled value <code>remote_controlled_string</code>. An attacker could craft <code>remote_controlled_string</code> to change the overall meaning of the SQL query.
</p>
<sample src="SqlInjectionBad.rs" />
<p>A better way to do this is with a prepared statement, binding <code>remote_controlled_string</code> to a parameter of that statement. An attacker who controls <code>remote_controlled_string</code> now cannot change the overall meaning of the query.
</p>
<sample src="SqlInjectionGood.rs" />
</example>
<references>
<li>Wikipedia: <a href="https://en.wikipedia.org/wiki/SQL_injection">SQL injection</a>.</li>
<li>OWASP: <a href="https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html">SQL Injection Prevention Cheat Sheet</a>.</li>
</references>
</qhelp>

View File

@@ -0,0 +1,35 @@
/**
* @name Database query built from user-controlled sources
* @description Building a database query from user-controlled sources is vulnerable to insertion of malicious code by attackers.
* @kind path-problem
* @problem.severity error
* @security-severity 8.8
* @precision high
* @id rust/sql-injection
* @tags security
* external/cwe/cwe-089
*/
import rust
import codeql.rust.dataflow.DataFlow
import codeql.rust.dataflow.TaintTracking
import codeql.rust.security.SqlInjectionExtensions
import SqlInjectionFlow::PathGraph
/**
* A taint configuration for tainted data that reaches a SQL sink.
*/
module SqlInjectionConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node node) { node instanceof SqlInjection::Source }
predicate isSink(DataFlow::Node node) { node instanceof SqlInjection::Sink }
predicate isBarrier(DataFlow::Node barrier) { barrier instanceof SqlInjection::Barrier }
}
module SqlInjectionFlow = TaintTracking::Global<SqlInjectionConfig>;
from SqlInjectionFlow::PathNode sourceNode, SqlInjectionFlow::PathNode sinkNode
where SqlInjectionFlow::flowPath(sourceNode, sinkNode)
select sinkNode.getNode(), sourceNode, sinkNode, "This query depends on a $@.",
sourceNode.getNode(), "user-provided value"

View File

@@ -0,0 +1,7 @@
// with SQLx
let unsafe_query = format!("SELECT * FROM people WHERE firstname='{remote_controlled_string}'");
let _ = conn.execute(unsafe_query.as_str()).await?; // BAD (arbitrary SQL injection is possible)
let _ = sqlx::query(unsafe_query.as_str()).fetch_all(&mut conn).await?; // BAD (arbitrary SQL injection is possible)

View File

@@ -0,0 +1,5 @@
// with SQLx
let prepared_query = "SELECT * FROM people WHERE firstname=?";
let _ = sqlx::query(prepared_query_1).bind(&remote_controlled_string).fetch_all(&mut conn).await?; // GOOD (prepared statement with bound parameter)

View File

@@ -31,8 +31,10 @@ FieldExpr/gen_field_expr.rs 9a70500d592e0a071b03d974a55558b3bc0df531ff11bce5898f
FnPtrType/gen_fn_ptr_type.rs a7842d8c21636739d1be959e5ce5e0b23482d5ef6eab5c45b009895da8175932 a7842d8c21636739d1be959e5ce5e0b23482d5ef6eab5c45b009895da8175932
ForExpr/gen_for_expr.rs 67decf3073e1a9363d9df05a5a64a6059349e50b81356f480f7aeb352189136d 67decf3073e1a9363d9df05a5a64a6059349e50b81356f480f7aeb352189136d
ForType/gen_for_type.rs 6cb447df02c61b192e283e019576c28225added02d167030d64ebd0bebb1b158 6cb447df02c61b192e283e019576c28225added02d167030d64ebd0bebb1b158
FormatArgsArg/gen_format_args_arg.rs c466f2fc2c0f9592061a159a217a87551d67f1ccb0e4d8f7f56a463a2aa4a73a c466f2fc2c0f9592061a159a217a87551d67f1ccb0e4d8f7f56a463a2aa4a73a
FormatArgsExpr/gen_format_args_expr.rs 7184dbb8833f970676e59fca3a40ec51d14a68e3151d8a6d637896494f2b4454 7184dbb8833f970676e59fca3a40ec51d14a68e3151d8a6d637896494f2b4454
FormatArgsExpr/gen_format.rs bd009cb152c35e2aacd147b5520a42be31e66e9a8715ec1d0fd57b8e97c743ed bd009cb152c35e2aacd147b5520a42be31e66e9a8715ec1d0fd57b8e97c743ed
FormatArgsExpr/gen_format_args_arg.rs c466f2fc2c0f9592061a159a217a87551d67f1ccb0e4d8f7f56a463a2aa4a73a c466f2fc2c0f9592061a159a217a87551d67f1ccb0e4d8f7f56a463a2aa4a73a
FormatArgsExpr/gen_format_args_expr.rs 72c806ed163e9dcce2d0c5c8664d409b2aa635c1022c91959f9e8ae084f05bf2 72c806ed163e9dcce2d0c5c8664d409b2aa635c1022c91959f9e8ae084f05bf2
FormatArgsExpr/gen_format_argument.rs 350d370e6f1db03d756384a3dbdb294697d241ff7c28d159cf57748abe99cfe9 350d370e6f1db03d756384a3dbdb294697d241ff7c28d159cf57748abe99cfe9
Function/gen_function.rs ba6ecb9e0d89183295eb02f3c20ebbf5c209f89bd0172c73a3b4a6dacbf3a54c ba6ecb9e0d89183295eb02f3c20ebbf5c209f89bd0172c73a3b4a6dacbf3a54c
GenericArgList/gen_generic_arg_list.rs cfb072d3b48f9dd568c23d4dfefba28766628678f66bbf9a436de9919ead35f5 cfb072d3b48f9dd568c23d4dfefba28766628678f66bbf9a436de9919ead35f5
GenericParamList/gen_generic_param_list.rs 4cc9b628f53e1a6c5781ad195b8648fa6dee0bb41b24007fbd986527374d3669 4cc9b628f53e1a6c5781ad195b8648fa6dee0bb41b24007fbd986527374d3669

View File

@@ -33,8 +33,10 @@
/FnPtrType/gen_fn_ptr_type.rs linguist-generated
/ForExpr/gen_for_expr.rs linguist-generated
/ForType/gen_for_type.rs linguist-generated
/FormatArgsArg/gen_format_args_arg.rs linguist-generated
/FormatArgsExpr/gen_format.rs linguist-generated
/FormatArgsExpr/gen_format_args_arg.rs linguist-generated
/FormatArgsExpr/gen_format_args_expr.rs linguist-generated
/FormatArgsExpr/gen_format_argument.rs linguist-generated
/Function/gen_function.rs linguist-generated
/GenericArgList/gen_generic_arg_list.rs linguist-generated
/GenericParamList/gen_generic_param_list.rs linguist-generated

View File

@@ -0,0 +1,9 @@
| gen_format.rs:5:21:5:22 | {} | getParent: | gen_format.rs:5:14:5:32 | FormatArgsExpr | getIndex: | 1 | hasArgument: | no |
| gen_format_args_expr.rs:6:19:6:20 | {} | getParent: | gen_format_args_expr.rs:6:17:6:37 | FormatArgsExpr | getIndex: | 1 | hasArgument: | no |
| gen_format_args_expr.rs:6:26:6:29 | {:?} | getParent: | gen_format_args_expr.rs:6:17:6:37 | FormatArgsExpr | getIndex: | 3 | hasArgument: | no |
| gen_format_args_expr.rs:7:19:7:21 | {b} | getParent: | gen_format_args_expr.rs:7:17:7:43 | FormatArgsExpr | getIndex: | 1 | hasArgument: | yes |
| gen_format_args_expr.rs:7:27:7:31 | {a:?} | getParent: | gen_format_args_expr.rs:7:17:7:43 | FormatArgsExpr | getIndex: | 3 | hasArgument: | yes |
| gen_format_args_expr.rs:9:19:9:21 | {x} | getParent: | gen_format_args_expr.rs:9:17:9:28 | FormatArgsExpr | getIndex: | 1 | hasArgument: | yes |
| gen_format_args_expr.rs:9:24:9:26 | {y} | getParent: | gen_format_args_expr.rs:9:17:9:28 | FormatArgsExpr | getIndex: | 3 | hasArgument: | yes |
| gen_format_argument.rs:5:21:5:46 | {value:#width$.precision$} | getParent: | gen_format_argument.rs:5:14:5:47 | FormatArgsExpr | getIndex: | 1 | hasArgument: | yes |
| gen_format_argument.rs:7:21:7:30 | {0:#1$.2$} | getParent: | gen_format_argument.rs:7:14:7:56 | FormatArgsExpr | getIndex: | 1 | hasArgument: | yes |

View File

@@ -0,0 +1,12 @@
// generated by codegen, do not edit
import codeql.rust.elements
import TestUtils
from Format x, FormatArgsExpr getParent, int getIndex, string hasArgument
where
toBeTested(x) and
not x.isUnknown() and
getParent = x.getParent() and
getIndex = x.getIndex() and
if x.hasArgument() then hasArgument = "yes" else hasArgument = "no"
select x, "getParent:", getParent, "getIndex:", getIndex, "hasArgument:", hasArgument

View File

@@ -0,0 +1,8 @@
| gen_format.rs:5:26:5:32 | FormatArgsArg | hasExpr: | yes | hasName: | no |
| gen_format_args_expr.rs:6:33:6:33 | FormatArgsArg | hasExpr: | yes | hasName: | no |
| gen_format_args_expr.rs:6:36:6:36 | FormatArgsArg | hasExpr: | yes | hasName: | no |
| gen_format_args_expr.rs:7:35:7:37 | FormatArgsArg | hasExpr: | yes | hasName: | yes |
| gen_format_args_expr.rs:7:40:7:42 | FormatArgsArg | hasExpr: | yes | hasName: | yes |
| gen_format_argument.rs:7:34:7:38 | FormatArgsArg | hasExpr: | yes | hasName: | no |
| gen_format_argument.rs:7:41:7:45 | FormatArgsArg | hasExpr: | yes | hasName: | no |
| gen_format_argument.rs:7:48:7:56 | FormatArgsArg | hasExpr: | yes | hasName: | no |

View File

@@ -0,0 +1,8 @@
| gen_format.rs:5:26:5:32 | FormatArgsArg | gen_format.rs:5:26:5:32 | "world" |
| gen_format_args_expr.rs:6:33:6:33 | FormatArgsArg | gen_format_args_expr.rs:6:33:6:33 | 1 |
| gen_format_args_expr.rs:6:36:6:36 | FormatArgsArg | gen_format_args_expr.rs:6:36:6:36 | 2 |
| gen_format_args_expr.rs:7:35:7:37 | FormatArgsArg | gen_format_args_expr.rs:7:37:7:37 | 1 |
| gen_format_args_expr.rs:7:40:7:42 | FormatArgsArg | gen_format_args_expr.rs:7:42:7:42 | 2 |
| gen_format_argument.rs:7:34:7:38 | FormatArgsArg | gen_format_argument.rs:7:34:7:38 | value |
| gen_format_argument.rs:7:41:7:45 | FormatArgsArg | gen_format_argument.rs:7:41:7:45 | width |
| gen_format_argument.rs:7:48:7:56 | FormatArgsArg | gen_format_argument.rs:7:48:7:56 | precision |

View File

@@ -0,0 +1,2 @@
| gen_format_args_expr.rs:7:35:7:37 | FormatArgsArg | gen_format_args_expr.rs:7:35:7:35 | a |
| gen_format_args_expr.rs:7:40:7:42 | FormatArgsArg | gen_format_args_expr.rs:7:40:7:40 | b |

View File

@@ -0,0 +1,7 @@
| gen_format.rs:5:14:5:32 | FormatArgsExpr | getNumberOfArgs: | 1 | getNumberOfAttrs: | 0 | hasTemplate: | yes | getNumberOfFormats: | 1 |
| gen_format_args_expr.rs:5:17:5:27 | FormatArgsExpr | getNumberOfArgs: | 0 | getNumberOfAttrs: | 0 | hasTemplate: | yes | getNumberOfFormats: | 0 |
| gen_format_args_expr.rs:6:17:6:37 | FormatArgsExpr | getNumberOfArgs: | 2 | getNumberOfAttrs: | 0 | hasTemplate: | yes | getNumberOfFormats: | 2 |
| gen_format_args_expr.rs:7:17:7:43 | FormatArgsExpr | getNumberOfArgs: | 2 | getNumberOfAttrs: | 0 | hasTemplate: | yes | getNumberOfFormats: | 2 |
| gen_format_args_expr.rs:9:17:9:28 | FormatArgsExpr | getNumberOfArgs: | 0 | getNumberOfAttrs: | 0 | hasTemplate: | yes | getNumberOfFormats: | 2 |
| gen_format_argument.rs:5:14:5:47 | FormatArgsExpr | getNumberOfArgs: | 0 | getNumberOfAttrs: | 0 | hasTemplate: | yes | getNumberOfFormats: | 1 |
| gen_format_argument.rs:7:14:7:56 | FormatArgsExpr | getNumberOfArgs: | 3 | getNumberOfAttrs: | 0 | hasTemplate: | yes | getNumberOfFormats: | 1 |

View File

@@ -2,12 +2,15 @@
import codeql.rust.elements
import TestUtils
from FormatArgsExpr x, int getNumberOfArgs, int getNumberOfAttrs, string hasTemplate
from
FormatArgsExpr x, int getNumberOfArgs, int getNumberOfAttrs, string hasTemplate,
int getNumberOfFormats
where
toBeTested(x) and
not x.isUnknown() and
getNumberOfArgs = x.getNumberOfArgs() and
getNumberOfAttrs = x.getNumberOfAttrs() and
if x.hasTemplate() then hasTemplate = "yes" else hasTemplate = "no"
(if x.hasTemplate() then hasTemplate = "yes" else hasTemplate = "no") and
getNumberOfFormats = x.getNumberOfFormats()
select x, "getNumberOfArgs:", getNumberOfArgs, "getNumberOfAttrs:", getNumberOfAttrs,
"hasTemplate:", hasTemplate
"hasTemplate:", hasTemplate, "getNumberOfFormats:", getNumberOfFormats

View File

@@ -0,0 +1,8 @@
| gen_format.rs:5:14:5:32 | FormatArgsExpr | 0 | gen_format.rs:5:26:5:32 | FormatArgsArg |
| gen_format_args_expr.rs:6:17:6:37 | FormatArgsExpr | 0 | gen_format_args_expr.rs:6:33:6:33 | FormatArgsArg |
| gen_format_args_expr.rs:6:17:6:37 | FormatArgsExpr | 1 | gen_format_args_expr.rs:6:36:6:36 | FormatArgsArg |
| gen_format_args_expr.rs:7:17:7:43 | FormatArgsExpr | 0 | gen_format_args_expr.rs:7:35:7:37 | FormatArgsArg |
| gen_format_args_expr.rs:7:17:7:43 | FormatArgsExpr | 1 | gen_format_args_expr.rs:7:40:7:42 | FormatArgsArg |
| gen_format_argument.rs:7:14:7:56 | FormatArgsExpr | 0 | gen_format_argument.rs:7:34:7:38 | FormatArgsArg |
| gen_format_argument.rs:7:14:7:56 | FormatArgsExpr | 1 | gen_format_argument.rs:7:41:7:45 | FormatArgsArg |
| gen_format_argument.rs:7:14:7:56 | FormatArgsExpr | 2 | gen_format_argument.rs:7:48:7:56 | FormatArgsArg |

View File

@@ -0,0 +1,9 @@
| gen_format.rs:5:14:5:32 | FormatArgsExpr | 0 | gen_format.rs:5:21:5:22 | {} |
| gen_format_args_expr.rs:6:17:6:37 | FormatArgsExpr | 0 | gen_format_args_expr.rs:6:19:6:20 | {} |
| gen_format_args_expr.rs:6:17:6:37 | FormatArgsExpr | 1 | gen_format_args_expr.rs:6:26:6:29 | {:?} |
| gen_format_args_expr.rs:7:17:7:43 | FormatArgsExpr | 0 | gen_format_args_expr.rs:7:19:7:21 | {b} |
| gen_format_args_expr.rs:7:17:7:43 | FormatArgsExpr | 1 | gen_format_args_expr.rs:7:27:7:31 | {a:?} |
| gen_format_args_expr.rs:9:17:9:28 | FormatArgsExpr | 0 | gen_format_args_expr.rs:9:19:9:21 | {x} |
| gen_format_args_expr.rs:9:17:9:28 | FormatArgsExpr | 1 | gen_format_args_expr.rs:9:24:9:26 | {y} |
| gen_format_argument.rs:5:14:5:47 | FormatArgsExpr | 0 | gen_format_argument.rs:5:21:5:46 | {value:#width$.precision$} |
| gen_format_argument.rs:7:14:7:56 | FormatArgsExpr | 0 | gen_format_argument.rs:7:21:7:30 | {0:#1$.2$} |

View File

@@ -0,0 +1,7 @@
// generated by codegen, do not edit
import codeql.rust.elements
import TestUtils
from FormatArgsExpr x, int index
where toBeTested(x) and not x.isUnknown()
select x, index, x.getFormat(index)

View File

@@ -0,0 +1,7 @@
| gen_format.rs:5:14:5:32 | FormatArgsExpr | gen_format.rs:5:14:5:23 | "Hello {}\\n" |
| gen_format_args_expr.rs:5:17:5:27 | FormatArgsExpr | gen_format_args_expr.rs:5:18:5:26 | "no args" |
| gen_format_args_expr.rs:6:17:6:37 | FormatArgsExpr | gen_format_args_expr.rs:6:18:6:30 | "{} foo {:?}" |
| gen_format_args_expr.rs:7:17:7:43 | FormatArgsExpr | gen_format_args_expr.rs:7:18:7:32 | "{b} foo {a:?}" |
| gen_format_args_expr.rs:9:17:9:28 | FormatArgsExpr | gen_format_args_expr.rs:9:18:9:27 | "{x}, {y}" |
| gen_format_argument.rs:5:14:5:47 | FormatArgsExpr | gen_format_argument.rs:5:14:5:47 | "Value {value:#width$.precision$}\\n" |
| gen_format_argument.rs:7:14:7:56 | FormatArgsExpr | gen_format_argument.rs:7:14:7:31 | "Value {0:#1$.2$}\\n" |

View File

@@ -0,0 +1,5 @@
| gen_format_args_expr.rs:9:17:9:28 | FormatArgsExpr | 1 | gen_format_args_expr.rs:9:20:9:20 | x |
| gen_format_args_expr.rs:9:17:9:28 | FormatArgsExpr | 3 | gen_format_args_expr.rs:9:25:9:25 | y |
| gen_format_argument.rs:5:14:5:47 | FormatArgsExpr | 1 | gen_format_argument.rs:5:22:5:26 | value |
| gen_format_argument.rs:5:14:5:47 | FormatArgsExpr | 1 | gen_format_argument.rs:5:29:5:33 | width |
| gen_format_argument.rs:5:14:5:47 | FormatArgsExpr | 1 | gen_format_argument.rs:5:36:5:44 | precision |

View File

@@ -0,0 +1,10 @@
| gen_format_args_expr.rs:7:20:7:20 | b | getParent: | gen_format_args_expr.rs:7:19:7:21 | {b} | hasVariable: | no |
| gen_format_args_expr.rs:7:28:7:28 | a | getParent: | gen_format_args_expr.rs:7:27:7:31 | {a:?} | hasVariable: | no |
| gen_format_args_expr.rs:9:20:9:20 | x | getParent: | gen_format_args_expr.rs:9:19:9:21 | {x} | hasVariable: | yes |
| gen_format_args_expr.rs:9:25:9:25 | y | getParent: | gen_format_args_expr.rs:9:24:9:26 | {y} | hasVariable: | yes |
| gen_format_argument.rs:5:22:5:26 | value | getParent: | gen_format_argument.rs:5:21:5:46 | {value:#width$.precision$} | hasVariable: | yes |
| gen_format_argument.rs:5:29:5:33 | width | getParent: | gen_format_argument.rs:5:21:5:46 | {value:#width$.precision$} | hasVariable: | yes |
| gen_format_argument.rs:5:36:5:44 | precision | getParent: | gen_format_argument.rs:5:21:5:46 | {value:#width$.precision$} | hasVariable: | yes |
| gen_format_argument.rs:7:22:7:22 | 0 | getParent: | gen_format_argument.rs:7:21:7:30 | {0:#1$.2$} | hasVariable: | no |
| gen_format_argument.rs:7:25:7:25 | 1 | getParent: | gen_format_argument.rs:7:21:7:30 | {0:#1$.2$} | hasVariable: | no |
| gen_format_argument.rs:7:28:7:28 | 2 | getParent: | gen_format_argument.rs:7:21:7:30 | {0:#1$.2$} | hasVariable: | no |

View File

@@ -0,0 +1,11 @@
// generated by codegen, do not edit
import codeql.rust.elements
import TestUtils
from FormatArgument x, Format getParent, string hasVariable
where
toBeTested(x) and
not x.isUnknown() and
getParent = x.getParent() and
if x.hasVariable() then hasVariable = "yes" else hasVariable = "no"
select x, "getParent:", getParent, "hasVariable:", hasVariable

View File

@@ -0,0 +1,5 @@
| gen_format_args_expr.rs:9:20:9:20 | x | gen_format_args_expr.rs:9:20:9:20 | x |
| gen_format_args_expr.rs:9:25:9:25 | y | gen_format_args_expr.rs:9:25:9:25 | y |
| gen_format_argument.rs:5:22:5:26 | value | gen_format_argument.rs:5:22:5:26 | value |
| gen_format_argument.rs:5:29:5:33 | width | gen_format_argument.rs:5:29:5:33 | width |
| gen_format_argument.rs:5:36:5:44 | precision | gen_format_argument.rs:5:36:5:44 | precision |

View File

@@ -0,0 +1,7 @@
// generated by codegen, do not edit
import codeql.rust.elements
import TestUtils
from FormatArgument x
where toBeTested(x) and not x.isUnknown()
select x, x.getVariable()

View File

@@ -0,0 +1,5 @@
| gen_format_args_expr.rs:9:20:9:20 | x |
| gen_format_args_expr.rs:9:25:9:25 | y |
| gen_format_argument.rs:5:22:5:26 | value |
| gen_format_argument.rs:5:29:5:33 | width |
| gen_format_argument.rs:5:36:5:44 | precision |

View File

@@ -0,0 +1,7 @@
// generated by codegen, do not edit
import codeql.rust.elements
import TestUtils
from FormatTemplateVariableAccess x
where toBeTested(x) and not x.isUnknown()
select x

Some files were not shown because too many files have changed in this diff Show More