Compare commits

..

1 Commits

Author SHA1 Message Date
Owen Mansel-Chan
7126b95b16 Add test with MISSING alerts 2026-06-11 07:22:17 +02:00
375 changed files with 2193 additions and 12548 deletions

View File

@@ -1,2 +0,0 @@
description: Fix NameQualifier inconsistency
compatibility: full

View File

@@ -1071,7 +1071,7 @@ class NullPointerType extends BuiltInType {
* const float fa[40]; * const float fa[40];
* ``` * ```
*/ */
class DerivedType extends Type, NameQualifyingElement, @derivedtype { class DerivedType extends Type, @derivedtype {
override string toString() { result = this.getName() } override string toString() { result = this.getName() }
override string getName() { derivedtypes(underlyingElement(this), result, _, _) } override string getName() { derivedtypes(underlyingElement(this), result, _, _) }

View File

@@ -1430,8 +1430,7 @@ specialnamequalifyingelements(
@namequalifyingelement = @namespace @namequalifyingelement = @namespace
| @specialnamequalifyingelement | @specialnamequalifyingelement
| @usertype | @usertype
| @decltype | @decltype;
| @derivedtype;
namequalifiers( namequalifiers(
unique int id: @namequalifier, unique int id: @namequalifier,

View File

@@ -1,2 +0,0 @@
description: Fix NameQualifier inconsistency
compatibility: full

View File

@@ -1,7 +1,3 @@
| inconsistency2.cpp:3:3:3:5 | T:: | inconsistency2.cpp:3:3:3:6 | x | inconsistency2.cpp:2:20:2:20 | T |
| inconsistency2.cpp:3:3:3:11 | const s:: | inconsistency2.cpp:3:3:3:6 | x | file://:0:0:0:0 | const s |
| inconsistency.cpp:7:20:7:22 | S:: | inconsistency.cpp:7:20:7:23 | (int)... | inconsistency.cpp:4:8:4:8 | S |
| inconsistency.cpp:7:20:7:22 | S:: | inconsistency.cpp:7:20:7:23 | A | inconsistency.cpp:4:8:4:8 | S |
| name_qualifiers.cpp:29:7:29:8 | :: | name_qualifiers.cpp:29:7:29:9 | x | file://:0:0:0:0 | (global namespace) | | name_qualifiers.cpp:29:7:29:8 | :: | name_qualifiers.cpp:29:7:29:9 | x | file://:0:0:0:0 | (global namespace) |
| name_qualifiers.cpp:31:7:31:10 | N1:: | name_qualifiers.cpp:31:7:31:12 | nx | name_qualifiers.cpp:4:11:4:12 | N1 | | name_qualifiers.cpp:31:7:31:10 | N1:: | name_qualifiers.cpp:31:7:31:12 | nx | name_qualifiers.cpp:4:11:4:12 | N1 |
| name_qualifiers.cpp:34:7:34:8 | :: | name_qualifiers.cpp:34:9:34:12 | N1:: | file://:0:0:0:0 | (global namespace) | | name_qualifiers.cpp:34:7:34:8 | :: | name_qualifiers.cpp:34:9:34:12 | N1:: | file://:0:0:0:0 | (global namespace) |

View File

@@ -1,5 +1,7 @@
import cpp import cpp
from NameQualifier nq, Location l from NameQualifier nq, Location l
where l = nq.getQualifiedElement().getLocation() where
l = nq.getQualifiedElement().getLocation() and
l.getFile().getShortName() = "name_qualifiers"
select nq, nq.getQualifiedElement(), nq.getQualifyingElement() select nq, nq.getQualifiedElement(), nq.getQualifyingElement()

View File

@@ -1,8 +1,8 @@
// This file is present to test whether name-qualifying an enum constant leads to a database inconsistency. // This file is present to test whether name-qualifying an enum constant leads to a database inconsistency.
// As such, there is no QL part of the test.
struct S { enum E { A }; }; struct S { enum E { A }; };
static void f() { static int f() {
switch(0) { case S::A: break; } switch(0) { case S::A: break; }
} }

View File

@@ -1,12 +0,0 @@
namespace {
template <typename T> T f() {
T::x;
return {};
}
struct s {
static int x;
};
struct t {
s x = f<const s>();
};
}

View File

@@ -1,4 +1,4 @@
/** /*
* @name Web Cache Deception * @name Web Cache Deception
* @description A caching system has been detected on the application and is vulnerable to web cache deception. By manipulating the URL it is possible to force the application to cache pages that are only accessible by an authenticated user. Once cached, these pages can be accessed by an unauthenticated user. * @description A caching system has been detected on the application and is vulnerable to web cache deception. By manipulating the URL it is possible to force the application to cache pages that are only accessible by an authenticated user. Once cached, these pages can be accessed by an unauthenticated user.
* @kind problem * @kind problem

View File

@@ -54,31 +54,31 @@ func main() {}
// bad is an example of a bad implementation // bad is an example of a bad implementation
func (ld *Ldap) bad(req *http.Request) { func (ld *Ldap) bad(req *http.Request) {
// ... // ...
untrusted := req.UserAgent() // $ Source untrusted := req.UserAgent()
goldap.NewSearchRequest( goldap.NewSearchRequest(
untrusted, // $ Alert // BAD: untrusted dn untrusted, // BAD: untrusted dn
goldap.ScopeWholeSubtree, goldap.NeverDerefAliases, 0, 0, false, goldap.ScopeWholeSubtree, goldap.NeverDerefAliases, 0, 0, false,
"(&(objectClass=organizationalPerson))"+untrusted, // $ Alert // BAD: untrusted filter "(&(objectClass=organizationalPerson))"+untrusted, // BAD: untrusted filter
[]string{"dn", "cn", untrusted}, // $ Alert // BAD: untrusted attribute []string{"dn", "cn", untrusted}, // BAD: untrusted attribute
nil, nil,
) )
goldapv3.NewSearchRequest( goldapv3.NewSearchRequest(
untrusted, // $ Alert // BAD: untrusted dn untrusted, // BAD: untrusted dn
goldap.ScopeWholeSubtree, goldap.NeverDerefAliases, 0, 0, false, goldap.ScopeWholeSubtree, goldap.NeverDerefAliases, 0, 0, false,
"(&(objectClass=organizationalPerson))"+untrusted, // $ Alert // BAD: untrusted filter "(&(objectClass=organizationalPerson))"+untrusted, // BAD: untrusted filter
[]string{"dn", "cn", untrusted}, // $ Alert // BAD: untrusted attribute []string{"dn", "cn", untrusted}, // BAD: untrusted attribute
nil, nil,
) )
gopkgldapv2.NewSearchRequest( gopkgldapv2.NewSearchRequest(
untrusted, // $ Alert // BAD: untrusted dn untrusted, // BAD: untrusted dn
goldap.ScopeWholeSubtree, goldap.NeverDerefAliases, 0, 0, false, goldap.ScopeWholeSubtree, goldap.NeverDerefAliases, 0, 0, false,
"(&(objectClass=organizationalPerson))"+untrusted, // $ Alert // BAD: untrusted filter "(&(objectClass=organizationalPerson))"+untrusted, // BAD: untrusted filter
[]string{"dn", "cn", untrusted}, // $ Alert // BAD: untrusted attribute []string{"dn", "cn", untrusted}, // BAD: untrusted attribute
nil, nil,
) )
client := &ldapclient.LDAPClient{} client := &ldapclient.LDAPClient{}
client.Authenticate(untrusted, "123456") // $ Alert // BAD: untrusted filter client.Authenticate(untrusted, "123456") // BAD: untrusted filter
client.GetGroupsOfUser(untrusted) // $ Alert // BAD: untrusted filter client.GetGroupsOfUser(untrusted) // BAD: untrusted filter
// ... // ...
} }

View File

@@ -1,4 +1,2 @@
query: experimental/CWE-090/LDAPInjection.ql query: experimental/CWE-090/LDAPInjection.ql
postprocess: postprocess: utils/test/PrettyPrintModels.ql
- utils/test/PrettyPrintModels.ql
- utils/test/InlineExpectationsTestQuery.ql

View File

@@ -1,4 +1,2 @@
query: experimental/CWE-203/Timing.ql query: experimental/CWE-203/Timing.ql
postprocess: postprocess: utils/test/PrettyPrintModels.ql
- utils/test/PrettyPrintModels.ql
- utils/test/InlineExpectationsTestQuery.ql

View File

@@ -12,9 +12,9 @@ func bad(w http.ResponseWriter, req *http.Request) (interface{}, error) {
secret := "MySuperSecretPasscode" secret := "MySuperSecretPasscode"
secretHeader := "X-Secret" secretHeader := "X-Secret"
headerSecret := req.Header.Get(secretHeader) // $ Source headerSecret := req.Header.Get(secretHeader)
secretStr := string(secret) secretStr := string(secret)
if len(headerSecret) != 0 && headerSecret != secretStr { // $ Alert if len(headerSecret) != 0 && headerSecret != secretStr {
return nil, fmt.Errorf("header %s=%s did not match expected secret", secretHeader, headerSecret) return nil, fmt.Errorf("header %s=%s did not match expected secret", secretHeader, headerSecret)
} }
return nil, nil return nil, nil
@@ -25,9 +25,9 @@ func bad2(w http.ResponseWriter, req *http.Request) (interface{}, error) {
secret := "MySuperSecretPasscode" secret := "MySuperSecretPasscode"
secretHeader := "X-Secret" secretHeader := "X-Secret"
headerSecret := req.Header.Get(secretHeader) // $ Source headerSecret := req.Header.Get(secretHeader)
secretStr := string(secret) secretStr := string(secret)
if len(headerSecret) != 0 && strings.Compare(headerSecret, secretStr) != 0 { // $ Alert if len(headerSecret) != 0 && strings.Compare(headerSecret, secretStr) != 0 {
return nil, fmt.Errorf("header %s=%s did not match expected secret", secretHeader, headerSecret) return nil, fmt.Errorf("header %s=%s did not match expected secret", secretHeader, headerSecret)
} }
return nil, nil return nil, nil
@@ -38,8 +38,8 @@ func bad4(w http.ResponseWriter, req *http.Request) (interface{}, error) {
secret := "MySuperSecretPasscode" secret := "MySuperSecretPasscode"
secretHeader := "X-Secret" secretHeader := "X-Secret"
headerSecret := req.Header.Get(secretHeader) // $ Source headerSecret := req.Header.Get(secretHeader)
if len(secret) != 0 && headerSecret != "SecretStringLiteral" { // $ Alert if len(secret) != 0 && headerSecret != "SecretStringLiteral" {
return nil, fmt.Errorf("header %s=%s did not match expected secret", secretHeader, headerSecret) return nil, fmt.Errorf("header %s=%s did not match expected secret", secretHeader, headerSecret)
} }
return nil, nil return nil, nil

View File

@@ -1,2 +1 @@
query: experimental/CWE-285/PamAuthBypass.ql experimental/CWE-285/PamAuthBypass.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -9,7 +9,7 @@ import (
func bad() error { func bad() error {
t, _ := pam.StartFunc("", "", func(s pam.Style, msg string) (string, error) { t, _ := pam.StartFunc("", "", func(s pam.Style, msg string) (string, error) {
return "", nil return "", nil
}) // $ Alert })
return t.Authenticate(0) return t.Authenticate(0)
} }

View File

@@ -15,7 +15,7 @@ func bad(w http.ResponseWriter, req *http.Request) (interface{}, error) {
ldapServer := "ldap.example.com" ldapServer := "ldap.example.com"
ldapPort := 389 ldapPort := 389
bindDN := "cn=admin,dc=example,dc=com" bindDN := "cn=admin,dc=example,dc=com"
bindPassword := req.URL.Query()["password"][0] // $ Source bindPassword := req.URL.Query()["password"][0]
// Connect to the LDAP server // Connect to the LDAP server
l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapPort)) l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapPort))
@@ -25,7 +25,7 @@ func bad(w http.ResponseWriter, req *http.Request) (interface{}, error) {
defer l.Close() defer l.Close()
// BAD: user input is not sanetized // BAD: user input is not sanetized
err = l.Bind(bindDN, bindPassword) // $ Alert err = l.Bind(bindDN, bindPassword)
if err != nil { if err != nil {
return fmt.Errorf("LDAP bind failed: %v", err), err return fmt.Errorf("LDAP bind failed: %v", err), err
} }
@@ -84,7 +84,7 @@ func bad2(req *http.Request) {
ldapPort := 389 ldapPort := 389
bindDN := "cn=admin,dc=example,dc=com" bindDN := "cn=admin,dc=example,dc=com"
// BAD : empty password // BAD : empty password
bindPassword := "" // $ Source bindPassword := ""
// Connect to the LDAP server // Connect to the LDAP server
l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapPort)) l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapPort))
@@ -94,7 +94,7 @@ func bad2(req *http.Request) {
defer l.Close() defer l.Close()
// BAD : bindPassword is empty // BAD : bindPassword is empty
err = l.Bind(bindDN, bindPassword) // $ Alert err = l.Bind(bindDN, bindPassword)
if err != nil { if err != nil {
log.Fatalf("LDAP bind failed: %v", err) log.Fatalf("LDAP bind failed: %v", err)
} }

View File

@@ -1,4 +1,2 @@
query: experimental/CWE-287/ImproperLdapAuth.ql query: experimental/CWE-287/ImproperLdapAuth.ql
postprocess: postprocess: utils/test/PrettyPrintModels.ql
- utils/test/PrettyPrintModels.ql
- utils/test/InlineExpectationsTestQuery.ql

View File

@@ -1,6 +1,3 @@
#select
| go-jose.v3.go:24:32:24:37 | JwtKey | go-jose.v3.go:13:21:13:33 | "AllYourBase" | go-jose.v3.go:24:32:24:37 | JwtKey | This $@. | go-jose.v3.go:13:21:13:33 | "AllYourBase" | Constant Key is used as JWT Secret key |
| golang-jwt-v5.go:27:9:27:15 | JwtKey1 | golang-jwt-v5.go:19:22:19:34 | "AllYourBase" | golang-jwt-v5.go:27:9:27:15 | JwtKey1 | This $@. | golang-jwt-v5.go:19:22:19:34 | "AllYourBase" | Constant Key is used as JWT Secret key |
edges edges
| go-jose.v3.go:13:14:13:34 | type conversion | go-jose.v3.go:24:32:24:37 | JwtKey | provenance | | | go-jose.v3.go:13:14:13:34 | type conversion | go-jose.v3.go:24:32:24:37 | JwtKey | provenance | |
| go-jose.v3.go:13:21:13:33 | "AllYourBase" | go-jose.v3.go:13:14:13:34 | type conversion | provenance | | | go-jose.v3.go:13:21:13:33 | "AllYourBase" | go-jose.v3.go:13:14:13:34 | type conversion | provenance | |
@@ -14,3 +11,6 @@ nodes
| golang-jwt-v5.go:19:22:19:34 | "AllYourBase" | semmle.label | "AllYourBase" | | golang-jwt-v5.go:19:22:19:34 | "AllYourBase" | semmle.label | "AllYourBase" |
| golang-jwt-v5.go:27:9:27:15 | JwtKey1 | semmle.label | JwtKey1 | | golang-jwt-v5.go:27:9:27:15 | JwtKey1 | semmle.label | JwtKey1 |
subpaths subpaths
#select
| go-jose.v3.go:24:32:24:37 | JwtKey | go-jose.v3.go:13:21:13:33 | "AllYourBase" | go-jose.v3.go:24:32:24:37 | JwtKey | This $@. | go-jose.v3.go:13:21:13:33 | "AllYourBase" | Constant Key is used as JWT Secret key |
| golang-jwt-v5.go:27:9:27:15 | JwtKey1 | golang-jwt-v5.go:19:22:19:34 | "AllYourBase" | golang-jwt-v5.go:27:9:27:15 | JwtKey1 | This $@. | golang-jwt-v5.go:19:22:19:34 | "AllYourBase" | Constant Key is used as JWT Secret key |

View File

@@ -1,2 +1 @@
query: experimental/CWE-321-V2/HardCodedKeys.ql experimental/CWE-321-V2/HardCodedKeys.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -10,7 +10,7 @@ import (
) )
// NOT OK // NOT OK
var JwtKey = []byte("AllYourBase") // $ Source var JwtKey = []byte("AllYourBase")
func main2(r *http.Request) { func main2(r *http.Request) {
signedToken := r.URL.Query().Get("signedToken") signedToken := r.URL.Query().Get("signedToken")
@@ -21,7 +21,7 @@ func verifyJWT(signedToken string) {
fmt.Println("verifying JWT") fmt.Println("verifying JWT")
DecodedToken, _ := jwt.ParseSigned(signedToken) DecodedToken, _ := jwt.ParseSigned(signedToken)
out := CustomerInfo{} out := CustomerInfo{}
if err := DecodedToken.Claims(JwtKey, &out); err != nil { // $ Alert if err := DecodedToken.Claims(JwtKey, &out); err != nil {
panic(err) panic(err)
} }
fmt.Printf("%v\n", out) fmt.Printf("%v\n", out)

View File

@@ -16,7 +16,7 @@ type CustomerInfo struct {
} }
// BAD constant key // BAD constant key
var JwtKey1 = []byte("AllYourBase") // $ Source var JwtKey1 = []byte("AllYourBase")
func main1(r *http.Request) { func main1(r *http.Request) {
signedToken := r.URL.Query().Get("signedToken") signedToken := r.URL.Query().Get("signedToken")
@@ -24,7 +24,7 @@ func main1(r *http.Request) {
} }
func LoadJwtKey(token *jwt.Token) (interface{}, error) { func LoadJwtKey(token *jwt.Token) (interface{}, error) {
return JwtKey1, nil // $ Alert return JwtKey1, nil
} }
func verifyJWT_golangjwt(signedToken string) { func verifyJWT_golangjwt(signedToken string) {

View File

@@ -7,37 +7,37 @@ import (
) )
func myHandler1(w http.ResponseWriter, r *http.Request) { func myHandler1(w http.ResponseWriter, r *http.Request) {
param1 := r.URL.Query()["param1"][0] // $ Source param1 := r.URL.Query()["param1"][0]
value, _ := strconv.Atoi(param1) value, _ := strconv.Atoi(param1)
out := 1337 / value // $ Alert out := 1337 / value
fmt.Println(out) fmt.Println(out)
} }
func myHandler2(w http.ResponseWriter, r *http.Request) { func myHandler2(w http.ResponseWriter, r *http.Request) {
param1 := r.URL.Query()["param1"][0] // $ Source param1 := r.URL.Query()["param1"][0]
value := int(param1[0]) value := int(param1[0])
out := 1337 / value // $ Alert out := 1337 / value
fmt.Println(out) fmt.Println(out)
} }
func myHandler3(w http.ResponseWriter, r *http.Request) { func myHandler3(w http.ResponseWriter, r *http.Request) {
param1 := r.URL.Query()["param1"][0] // $ Source param1 := r.URL.Query()["param1"][0]
value, _ := strconv.ParseInt(param1, 10, 64) value, _ := strconv.ParseInt(param1, 10, 64)
out := 1337 / value // $ Alert out := 1337 / value
fmt.Println(out) fmt.Println(out)
} }
func myHandler4(w http.ResponseWriter, r *http.Request) { func myHandler4(w http.ResponseWriter, r *http.Request) {
param1 := r.URL.Query()["param1"][0] // $ Source param1 := r.URL.Query()["param1"][0]
value, _ := strconv.ParseFloat(param1, 32) value, _ := strconv.ParseFloat(param1, 32)
out := 1337 / value // $ Alert out := 1337 / value
fmt.Println(out) fmt.Println(out)
} }
func myHandler5(w http.ResponseWriter, r *http.Request) { func myHandler5(w http.ResponseWriter, r *http.Request) {
param1 := r.URL.Query()["param1"][0] // $ Source param1 := r.URL.Query()["param1"][0]
value, _ := strconv.ParseUint(param1, 10, 64) value, _ := strconv.ParseUint(param1, 10, 64)
out := 1337 / value // $ Alert out := 1337 / value
fmt.Println(out) fmt.Println(out)
} }
@@ -51,10 +51,10 @@ func myHandler6(w http.ResponseWriter, r *http.Request) {
} }
func myHandler7(w http.ResponseWriter, r *http.Request) { func myHandler7(w http.ResponseWriter, r *http.Request) {
param1 := r.URL.Query()["param1"][0] // $ Source param1 := r.URL.Query()["param1"][0]
value := int(param1[0]) value := int(param1[0])
if value >= 0 { if value >= 0 {
out := 1337 / value // $ Alert out := 1337 / value
fmt.Println(out) fmt.Println(out)
} }
} }

View File

@@ -1,4 +1,2 @@
query: experimental/CWE-369/DivideByZero.ql query: experimental/CWE-369/DivideByZero.ql
postprocess: postprocess: utils/test/PrettyPrintModels.ql
- utils/test/PrettyPrintModels.ql
- utils/test/InlineExpectationsTestQuery.ql

View File

@@ -1,7 +1,3 @@
#select
| DatabaseCallInLoop.go:9:3:9:41 | call to First | DatabaseCallInLoop.go:7:2:11:2 | range statement | DatabaseCallInLoop.go:9:3:9:41 | call to First | This calls call to First in a $@. | DatabaseCallInLoop.go:7:2:11:2 | range statement | loop |
| test.go:11:2:11:13 | call to Take | test.go:20:2:22:2 | for statement | test.go:11:2:11:13 | call to Take | This calls call to Take in a $@. | test.go:20:2:22:2 | for statement | loop |
| test.go:11:2:11:13 | call to Take | test.go:24:2:26:2 | for statement | test.go:11:2:11:13 | call to Take | This calls call to Take in a $@. | test.go:24:2:26:2 | for statement | loop |
edges edges
| DatabaseCallInLoop.go:7:2:11:2 | range statement | DatabaseCallInLoop.go:9:3:9:41 | call to First | | DatabaseCallInLoop.go:7:2:11:2 | range statement | DatabaseCallInLoop.go:9:3:9:41 | call to First |
| test.go:10:1:12:1 | function declaration | test.go:11:2:11:13 | call to Take | | test.go:10:1:12:1 | function declaration | test.go:11:2:11:13 | call to Take |
@@ -11,3 +7,7 @@ edges
| test.go:21:3:21:14 | call to runQuery | test.go:10:1:12:1 | function declaration | | test.go:21:3:21:14 | call to runQuery | test.go:10:1:12:1 | function declaration |
| test.go:24:2:26:2 | for statement | test.go:25:3:25:17 | call to runRunQuery | | test.go:24:2:26:2 | for statement | test.go:25:3:25:17 | call to runRunQuery |
| test.go:25:3:25:17 | call to runRunQuery | test.go:14:1:16:1 | function declaration | | test.go:25:3:25:17 | call to runRunQuery | test.go:14:1:16:1 | function declaration |
#select
| DatabaseCallInLoop.go:9:3:9:41 | call to First | DatabaseCallInLoop.go:7:2:11:2 | range statement | DatabaseCallInLoop.go:9:3:9:41 | call to First | This calls call to First in a $@. | DatabaseCallInLoop.go:7:2:11:2 | range statement | loop |
| test.go:11:2:11:13 | call to Take | test.go:20:2:22:2 | for statement | test.go:11:2:11:13 | call to Take | This calls call to Take in a $@. | test.go:20:2:22:2 | for statement | loop |
| test.go:11:2:11:13 | call to Take | test.go:24:2:26:2 | for statement | test.go:11:2:11:13 | call to Take | This calls call to Take in a $@. | test.go:24:2:26:2 | for statement | loop |

View File

@@ -6,8 +6,8 @@ func getUsers(db *gorm.DB, names []string) []User {
res := make([]User, 0, len(names)) res := make([]User, 0, len(names))
for _, name := range names { for _, name := range names {
var user User var user User
db.Where("name = ?", name).First(&user) // $ Alert db.Where("name = ?", name).First(&user)
res = append(res, user) res = append(res, user)
} // $ Source }
return res return res
} }

View File

@@ -1,2 +1 @@
query: experimental/CWE-400/DatabaseCallInLoop.ql experimental/CWE-400/DatabaseCallInLoop.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -8,7 +8,7 @@ type User struct {
} }
func runQuery(db *gorm.DB) { func runQuery(db *gorm.DB) {
db.Take(nil) // $ Alert db.Take(nil)
} }
func runRunQuery(db *gorm.DB) { func runRunQuery(db *gorm.DB) {
@@ -19,9 +19,9 @@ func main() {
var db *gorm.DB var db *gorm.DB
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
runQuery(db) runQuery(db)
} // $ Source }
for i := 10; i > 0; i-- { for i := 10; i > 0; i-- {
runRunQuery(db) runRunQuery(db)
} // $ Source }
} }

View File

@@ -1,4 +1,2 @@
query: experimental/CWE-522-DecompressionBombs/DecompressionBombs.ql query: experimental/CWE-522-DecompressionBombs/DecompressionBombs.ql
postprocess: postprocess: utils/test/PrettyPrintModels.ql
- utils/test/PrettyPrintModels.ql
- utils/test/InlineExpectationsTestQuery.ql

View File

@@ -56,41 +56,41 @@ func main() {
func DecompressHandler(w http.ResponseWriter, request *http.Request) { func DecompressHandler(w http.ResponseWriter, request *http.Request) {
GZipOpenReaderSafe(request.PostFormValue("test")) GZipOpenReaderSafe(request.PostFormValue("test"))
ZipOpenReaderSafe(request.PostFormValue("test")) ZipOpenReaderSafe(request.PostFormValue("test"))
ZipOpenReader(request.FormValue("filepath")) // $ Source ZipOpenReader(request.FormValue("filepath"))
ZipNewReader(request.Body) // $ Source ZipNewReader(request.Body)
ZipNewReaderKlauspost(request.Body) // $ Source ZipNewReaderKlauspost(request.Body)
Bzip2Dsnet(request.Body) // $ Source Bzip2Dsnet(request.Body)
Bzip2DsnetSafe(request.Body) Bzip2DsnetSafe(request.Body)
Bzip2(request.Body) // $ Source Bzip2(request.Body)
Bzip2Safe(request.Body) Bzip2Safe(request.Body)
Flate(request.Body) // $ Source Flate(request.Body)
FlateSafe(request.Body) FlateSafe(request.Body)
FlateKlauspost(request.Body) // $ Source FlateKlauspost(request.Body)
FlateKlauspostSafe(request.Body) FlateKlauspostSafe(request.Body)
FlateDsnet(request.Body) // $ Source FlateDsnet(request.Body)
FlateDsnetSafe(request.Body) FlateDsnetSafe(request.Body)
ZlibKlauspost(request.Body) // $ Source ZlibKlauspost(request.Body)
ZlibKlauspostSafe(request.Body) ZlibKlauspostSafe(request.Body)
Zlib(request.Body) // $ Source Zlib(request.Body)
ZlibSafe(request.Body) ZlibSafe(request.Body)
Snappy(request.Body) // $ Source Snappy(request.Body)
SnappySafe(request.Body) SnappySafe(request.Body)
SnappyKlauspost(request.Body) // $ Source SnappyKlauspost(request.Body)
SnappyKlauspostSafe(request.Body) SnappyKlauspostSafe(request.Body)
S2(request.Body) // $ Source S2(request.Body)
S2Safe(request.Body) S2Safe(request.Body)
Gzip(request.Body) // $ Source Gzip(request.Body)
GzipSafe(request.Body) GzipSafe(request.Body)
GZipIoReader(request.Body, "dest") // $ Source GZipIoReader(request.Body, "dest")
GzipKlauspost(request.Body) // $ Source GzipKlauspost(request.Body)
GzipKlauspostSafe(request.Body) GzipKlauspostSafe(request.Body)
PzipKlauspost(request.Body) // $ Source PzipKlauspost(request.Body)
PzipKlauspostSafe(request.Body) PzipKlauspostSafe(request.Body)
Zstd_Klauspost(request.Body) // $ Source Zstd_Klauspost(request.Body)
Zstd_KlauspostSafe(request.Body) Zstd_KlauspostSafe(request.Body)
Zstd_DataDog(request.Body) // $ Source Zstd_DataDog(request.Body)
Zstd_DataDogSafe(request.Body) Zstd_DataDogSafe(request.Body)
Xz(request.Body) // $ Source Xz(request.Body)
XzSafe(request.Body) XzSafe(request.Body)
} }
@@ -131,7 +131,7 @@ func ZipOpenReader(filename string) {
for _, f := range zipReader.File { for _, f := range zipReader.File {
rc, _ := f.Open() rc, _ := f.Open()
for { for {
result, _ := io.CopyN(os.Stdout, rc, 68) // $ hasValueFlow="rc" Alert result, _ := io.CopyN(os.Stdout, rc, 68) // $ hasValueFlow="rc"
if result == 0 { if result == 0 {
_ = rc.Close() _ = rc.Close()
break break
@@ -144,7 +144,7 @@ func ZipOpenReader(filename string) {
for _, f := range zipKlauspostReader.File { for _, f := range zipKlauspostReader.File {
rc, _ := f.Open() rc, _ := f.Open()
for { for {
result, _ := io.CopyN(os.Stdout, rc, 68) // $ hasValueFlow="rc" Alert result, _ := io.CopyN(os.Stdout, rc, 68) // $ hasValueFlow="rc"
if result == 0 { if result == 0 {
_ = rc.Close() _ = rc.Close()
break break
@@ -161,7 +161,7 @@ func ZipNewReader(file io.Reader) {
for _, file := range zipReader.File { for _, file := range zipReader.File {
fileWriter := bytes.NewBuffer([]byte{}) fileWriter := bytes.NewBuffer([]byte{})
fileReaderCloser, _ := file.Open() fileReaderCloser, _ := file.Open()
result, _ := io.Copy(fileWriter, fileReaderCloser) // $ hasValueFlow="fileReaderCloser" Alert result, _ := io.Copy(fileWriter, fileReaderCloser) // $ hasValueFlow="fileReaderCloser"
fmt.Print(result) fmt.Print(result)
} }
} }
@@ -173,7 +173,7 @@ func ZipNewReaderKlauspost(file io.Reader) {
fileWriter := bytes.NewBuffer([]byte{}) fileWriter := bytes.NewBuffer([]byte{})
// file.OpenRaw() // file.OpenRaw()
fileReaderCloser, _ := file.Open() fileReaderCloser, _ := file.Open()
result, _ := io.Copy(fileWriter, fileReaderCloser) // $ hasValueFlow="fileReaderCloser" Alert result, _ := io.Copy(fileWriter, fileReaderCloser) // $ hasValueFlow="fileReaderCloser"
fmt.Print(result) fmt.Print(result)
} }
} }
@@ -183,7 +183,7 @@ func Bzip2Dsnet(file io.Reader) {
bzip2Reader, _ := bzip2Dsnet.NewReader(file, &bzip2Dsnet.ReaderConfig{}) bzip2Reader, _ := bzip2Dsnet.NewReader(file, &bzip2Dsnet.ReaderConfig{})
var out []byte = make([]byte, 70) var out []byte = make([]byte, 70)
bzip2Reader.Read(out) // $ hasValueFlow="bzip2Reader" Alert bzip2Reader.Read(out) // $ hasValueFlow="bzip2Reader"
tarRead = tar.NewReader(bzip2Reader) tarRead = tar.NewReader(bzip2Reader)
TarDecompressor(tarRead) TarDecompressor(tarRead)
@@ -210,7 +210,7 @@ func Bzip2(file io.Reader) {
bzip2Reader := bzip2.NewReader(file) bzip2Reader := bzip2.NewReader(file)
var out []byte = make([]byte, 70) var out []byte = make([]byte, 70)
bzip2Reader.Read(out) // $ hasValueFlow="bzip2Reader" Alert bzip2Reader.Read(out) // $ hasValueFlow="bzip2Reader"
tarRead = tar.NewReader(bzip2Reader) tarRead = tar.NewReader(bzip2Reader)
TarDecompressor(tarRead) TarDecompressor(tarRead)
@@ -235,7 +235,7 @@ func Flate(file io.Reader) {
flateReader := flate.NewReader(file) flateReader := flate.NewReader(file)
var out []byte = make([]byte, 70) var out []byte = make([]byte, 70)
flateReader.Read(out) // $ hasValueFlow="flateReader" Alert flateReader.Read(out) // $ hasValueFlow="flateReader"
tarRead = tar.NewReader(flateReader) tarRead = tar.NewReader(flateReader)
TarDecompressor(tarRead) TarDecompressor(tarRead)
@@ -260,7 +260,7 @@ func FlateKlauspost(file io.Reader) {
flateReader := flateKlauspost.NewReader(file) flateReader := flateKlauspost.NewReader(file)
var out []byte = make([]byte, 70) var out []byte = make([]byte, 70)
flateReader.Read(out) // $ hasValueFlow="flateReader" Alert flateReader.Read(out) // $ hasValueFlow="flateReader"
tarRead = tar.NewReader(flateReader) tarRead = tar.NewReader(flateReader)
TarDecompressor(tarRead) TarDecompressor(tarRead)
@@ -285,7 +285,7 @@ func FlateDsnet(file io.Reader) {
flateReader, _ := flateDsnet.NewReader(file, &flateDsnet.ReaderConfig{}) flateReader, _ := flateDsnet.NewReader(file, &flateDsnet.ReaderConfig{})
var out []byte = make([]byte, 70) var out []byte = make([]byte, 70)
flateReader.Read(out) // $ hasValueFlow="flateReader" Alert flateReader.Read(out) // $ hasValueFlow="flateReader"
tarRead = tar.NewReader(flateReader) tarRead = tar.NewReader(flateReader)
TarDecompressor(tarRead) TarDecompressor(tarRead)
@@ -310,7 +310,7 @@ func ZlibKlauspost(file io.Reader) {
zlibReader, _ := zlibKlauspost.NewReader(file) zlibReader, _ := zlibKlauspost.NewReader(file)
var out []byte = make([]byte, 70) var out []byte = make([]byte, 70)
zlibReader.Read(out) // $ hasValueFlow="zlibReader" Alert zlibReader.Read(out) // $ hasValueFlow="zlibReader"
tarRead = tar.NewReader(zlibReader) tarRead = tar.NewReader(zlibReader)
TarDecompressor(tarRead) TarDecompressor(tarRead)
@@ -335,7 +335,7 @@ func Zlib(file io.Reader) {
zlibReader, _ := zlib.NewReader(file) zlibReader, _ := zlib.NewReader(file)
var out []byte = make([]byte, 70) var out []byte = make([]byte, 70)
zlibReader.Read(out) // $ hasValueFlow="zlibReader" Alert zlibReader.Read(out) // $ hasValueFlow="zlibReader"
tarRead = tar.NewReader(zlibReader) tarRead = tar.NewReader(zlibReader)
TarDecompressor(tarRead) TarDecompressor(tarRead)
@@ -360,8 +360,8 @@ func Snappy(file io.Reader) {
snappyReader := snappy.NewReader(file) snappyReader := snappy.NewReader(file)
var out []byte = make([]byte, 70) var out []byte = make([]byte, 70)
snappyReader.Read(out) // $ hasValueFlow="snappyReader" Alert snappyReader.Read(out) // $ hasValueFlow="snappyReader"
snappyReader.ReadByte() // $ hasValueFlow="snappyReader" Alert snappyReader.ReadByte() // $ hasValueFlow="snappyReader"
tarRead = tar.NewReader(snappyReader) tarRead = tar.NewReader(snappyReader)
TarDecompressor(tarRead) TarDecompressor(tarRead)
@@ -386,10 +386,10 @@ func SnappyKlauspost(file io.Reader) {
snappyReader := snappyKlauspost.NewReader(file) snappyReader := snappyKlauspost.NewReader(file)
var out []byte = make([]byte, 70) var out []byte = make([]byte, 70)
snappyReader.Read(out) // $ hasValueFlow="snappyReader" Alert snappyReader.Read(out) // $ hasValueFlow="snappyReader"
var buf bytes.Buffer var buf bytes.Buffer
snappyReader.DecodeConcurrent(&buf, 2) // $ hasValueFlow="snappyReader" Alert snappyReader.DecodeConcurrent(&buf, 2) // $ hasValueFlow="snappyReader"
snappyReader.ReadByte() // $ hasValueFlow="snappyReader" Alert snappyReader.ReadByte() // $ hasValueFlow="snappyReader"
tarRead = tar.NewReader(snappyReader) tarRead = tar.NewReader(snappyReader)
TarDecompressor(tarRead) TarDecompressor(tarRead)
@@ -414,10 +414,10 @@ func S2(file io.Reader) {
s2Reader := s2.NewReader(file) s2Reader := s2.NewReader(file)
var out []byte = make([]byte, 70) var out []byte = make([]byte, 70)
s2Reader.Read(out) // $ hasValueFlow="s2Reader" Alert s2Reader.Read(out) // $ hasValueFlow="s2Reader"
s2Reader.ReadByte() // $ hasValueFlow="s2Reader" Alert s2Reader.ReadByte() // $ hasValueFlow="s2Reader"
var buf bytes.Buffer var buf bytes.Buffer
s2Reader.DecodeConcurrent(&buf, 2) // $ hasValueFlow="s2Reader" Alert s2Reader.DecodeConcurrent(&buf, 2) // $ hasValueFlow="s2Reader"
tarRead = tar.NewReader(s2Reader) tarRead = tar.NewReader(s2Reader)
TarDecompressor(tarRead) TarDecompressor(tarRead)
@@ -442,14 +442,14 @@ func GZipIoReader(src io.Reader, dst string) {
dstF, _ := os.OpenFile(dst, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755) dstF, _ := os.OpenFile(dst, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755)
defer dstF.Close() defer dstF.Close()
newSrc := io.Reader(gzipReader) newSrc := io.Reader(gzipReader)
_, _ = io.Copy(dstF, newSrc) // $ hasValueFlow="newSrc" Alert _, _ = io.Copy(dstF, newSrc) // $ hasValueFlow="newSrc"
} }
func Gzip(file io.Reader) { func Gzip(file io.Reader) {
var tarRead *tar.Reader var tarRead *tar.Reader
gzipReader, _ := gzip.NewReader(file) gzipReader, _ := gzip.NewReader(file)
var out []byte = make([]byte, 70) var out []byte = make([]byte, 70)
gzipReader.Read(out) // $ hasValueFlow="gzipReader" Alert gzipReader.Read(out) // $ hasValueFlow="gzipReader"
tarRead = tar.NewReader(gzipReader) tarRead = tar.NewReader(gzipReader)
TarDecompressor(tarRead) TarDecompressor(tarRead)
@@ -474,9 +474,9 @@ func GzipKlauspost(file io.Reader) {
gzipReader, _ := gzipKlauspost.NewReader(file) gzipReader, _ := gzipKlauspost.NewReader(file)
var out []byte = make([]byte, 70) var out []byte = make([]byte, 70)
gzipReader.Read(out) // $ hasValueFlow="gzipReader" Alert gzipReader.Read(out) // $ hasValueFlow="gzipReader"
var buf bytes.Buffer var buf bytes.Buffer
gzipReader.WriteTo(&buf) // $ hasValueFlow="gzipReader" Alert gzipReader.WriteTo(&buf) // $ hasValueFlow="gzipReader"
tarRead = tar.NewReader(gzipReader) tarRead = tar.NewReader(gzipReader)
TarDecompressor(tarRead) TarDecompressor(tarRead)
@@ -501,9 +501,9 @@ func PzipKlauspost(file io.Reader) {
pgzipReader, _ := pgzipKlauspost.NewReader(file) pgzipReader, _ := pgzipKlauspost.NewReader(file)
var out []byte = make([]byte, 70) var out []byte = make([]byte, 70)
pgzipReader.Read(out) // $ hasValueFlow="pgzipReader" Alert pgzipReader.Read(out) // $ hasValueFlow="pgzipReader"
var buf bytes.Buffer var buf bytes.Buffer
pgzipReader.WriteTo(&buf) // $ hasValueFlow="pgzipReader" Alert pgzipReader.WriteTo(&buf) // $ hasValueFlow="pgzipReader"
tarRead = tar.NewReader(pgzipReader) tarRead = tar.NewReader(pgzipReader)
TarDecompressor(tarRead) TarDecompressor(tarRead)
@@ -528,11 +528,11 @@ func Zstd_Klauspost(file io.Reader) {
zstdReader, _ := zstdKlauspost.NewReader(file) zstdReader, _ := zstdKlauspost.NewReader(file)
var out []byte = make([]byte, 70) var out []byte = make([]byte, 70)
zstdReader.Read(out) // $ hasValueFlow="zstdReader" Alert zstdReader.Read(out) // $ hasValueFlow="zstdReader"
var buf bytes.Buffer var buf bytes.Buffer
zstdReader.WriteTo(&buf) // $ hasValueFlow="zstdReader" Alert zstdReader.WriteTo(&buf) // $ hasValueFlow="zstdReader"
var src []byte var src []byte
zstdReader.DecodeAll(src, nil) // $ hasValueFlow="zstdReader" Alert zstdReader.DecodeAll(src, nil) // $ hasValueFlow="zstdReader"
tarRead = tar.NewReader(zstdReader) tarRead = tar.NewReader(zstdReader)
TarDecompressor(tarRead) TarDecompressor(tarRead)
@@ -557,7 +557,7 @@ func Zstd_DataDog(file io.Reader) {
zstdReader := zstdDataDog.NewReader(file) zstdReader := zstdDataDog.NewReader(file)
var out []byte = make([]byte, 70) var out []byte = make([]byte, 70)
zstdReader.Read(out) // $ hasValueFlow="zstdReader" Alert zstdReader.Read(out) // $ hasValueFlow="zstdReader"
tarRead = tar.NewReader(zstdReader) tarRead = tar.NewReader(zstdReader)
TarDecompressor(tarRead) TarDecompressor(tarRead)
@@ -582,7 +582,7 @@ func Xz(file io.Reader) {
xzReader, _ := xz.NewReader(file) xzReader, _ := xz.NewReader(file)
var out []byte = make([]byte, 70) var out []byte = make([]byte, 70)
xzReader.Read(out) // $ hasValueFlow="xzReader" Alert xzReader.Read(out) // $ hasValueFlow="xzReader"
tarRead = tar.NewReader(xzReader) tarRead = tar.NewReader(xzReader)
fmt.Println(io.SeekStart) fmt.Println(io.SeekStart)
@@ -618,7 +618,7 @@ func TarDecompressor(tarRead *tar.Reader) {
if cur.Typeflag != tar.TypeReg { if cur.Typeflag != tar.TypeReg {
continue continue
} }
data, _ := io.ReadAll(tarRead) // $ hasValueFlow="tarRead" Alert data, _ := io.ReadAll(tarRead) // $ hasValueFlow="tarRead"
files[cur.Name] = &fstest.MapFile{Data: data} files[cur.Name] = &fstest.MapFile{Data: data}
} }
fmt.Print(files) fmt.Print(files)
@@ -626,7 +626,7 @@ func TarDecompressor(tarRead *tar.Reader) {
func TarDecompressor2(tarRead *tar.Reader) { func TarDecompressor2(tarRead *tar.Reader) {
var tarOut []byte = make([]byte, 70) var tarOut []byte = make([]byte, 70)
tarRead.Read(tarOut) // $ hasValueFlow="tarRead" Alert tarRead.Read(tarOut) // $ hasValueFlow="tarRead"
fmt.Println("do sth with output:", tarOut) fmt.Println("do sth with output:", tarOut)
} }

View File

@@ -1,2 +1 @@
query: experimental/CWE-525/WebCacheDeception.ql experimental/CWE-525/WebCacheDeception.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -79,7 +79,7 @@ func badRoutingNet() {
http.Handle("/assets/", http.StripPrefix("/assets/", http.FileServer(http.Dir("assets/")))) http.Handle("/assets/", http.StripPrefix("/assets/", http.FileServer(http.Dir("assets/"))))
http.HandleFunc("/adminusers/", ShowAdminPageCache) // $ Alert http.HandleFunc("/adminusers/", ShowAdminPageCache)
err := http.ListenAndServe(":1337", nil) err := http.ListenAndServe(":1337", nil)
if err != nil { if err != nil {
log.Fatal("ListenAndServe: ", err) log.Fatal("ListenAndServe: ", err)

View File

@@ -12,12 +12,12 @@ func badRouting() {
log.Println("We are logging in Golang!") log.Println("We are logging in Golang!")
// GET /api/register // GET /api/register
app.Get("/api/*", func(c *fiber.Ctx) error { // $ Alert app.Get("/api/*", func(c *fiber.Ctx) error {
msg := fmt.Sprintf("✋") msg := fmt.Sprintf("✋")
return c.SendString(msg) // => ✋ register return c.SendString(msg) // => ✋ register
}) })
app.Post("/api/*", func(c *fiber.Ctx) error { // $ Alert app.Post("/api/*", func(c *fiber.Ctx) error {
msg := fmt.Sprintf("✋") msg := fmt.Sprintf("✋")
return c.SendString(msg) // => ✋ register return c.SendString(msg) // => ✋ register
}) })

View File

@@ -10,7 +10,7 @@ import (
func badRoutingChi() { func badRoutingChi() {
r := chi.NewRouter() r := chi.NewRouter()
r.Use(middleware.Logger) r.Use(middleware.Logger)
r.Get("/*", func(w http.ResponseWriter, r *http.Request) { // $ Alert r.Get("/*", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("welcome")) w.Write([]byte("welcome"))
}) })
http.ListenAndServe(":3000", r) http.ListenAndServe(":3000", r)

View File

@@ -18,7 +18,7 @@ func Hello(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
func badHTTPRouter() { func badHTTPRouter() {
router := httprouter.New() router := httprouter.New()
router.GET("/test/*test", Index) // $ Alert router.GET("/test/*test", Index)
router.GET("/hello/:name", Hello) router.GET("/hello/:name", Hello)
log.Fatal(http.ListenAndServe(":8082", router)) log.Fatal(http.ListenAndServe(":8082", router))

View File

@@ -23,10 +23,10 @@ func good() (interface{}, error) {
} }
func bad() interface{} { func bad() interface{} {
name2 := os.Args[1:] // $ Source[go/dsn-injection-local] name2 := os.Args[1:]
// This is bad. `name` can be something like `test?allowAllFiles=true&` which will allow an attacker to access local files. // This is bad. `name` can be something like `test?allowAllFiles=true&` which will allow an attacker to access local files.
dbDSN := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8", "username", "password", "127.0.0.1", 3306, name2[0]) dbDSN := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8", "username", "password", "127.0.0.1", 3306, name2[0])
db, _ := sql.Open("mysql", dbDSN) // $ Alert[go/dsn-injection-local] db, _ := sql.Open("mysql", dbDSN)
return db return db
} }
@@ -44,10 +44,10 @@ func good2(w http.ResponseWriter, req *http.Request) (interface{}, error) {
} }
func bad2(w http.ResponseWriter, req *http.Request) interface{} { func bad2(w http.ResponseWriter, req *http.Request) interface{} {
name := req.FormValue("name") // $ Source[go/dsn-injection] name := req.FormValue("name")
// This is bad. `name` can be something like `test?allowAllFiles=true&` which will allow an attacker to access local files. // This is bad. `name` can be something like `test?allowAllFiles=true&` which will allow an attacker to access local files.
dbDSN := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8", "username", "password", "127.0.0.1", 3306, name) dbDSN := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8", "username", "password", "127.0.0.1", 3306, name)
db, _ := sql.Open("mysql", dbDSN) // $ Alert[go/dsn-injection] db, _ := sql.Open("mysql", dbDSN)
return db return db
} }
@@ -60,12 +60,12 @@ func (Config) Parse([]string) error { return nil }
func RegexFuncModelTest(w http.ResponseWriter, req *http.Request) (interface{}, error) { func RegexFuncModelTest(w http.ResponseWriter, req *http.Request) (interface{}, error) {
cfg := NewConfig() cfg := NewConfig()
err := cfg.Parse(os.Args[1:]) // $ Source[go/dsn-injection-local] // This is bad. `name` can be something like `test?allowAllFiles=true&` which will allow an attacker to access local files. err := cfg.Parse(os.Args[1:]) // This is bad. `name` can be something like `test?allowAllFiles=true&` which will allow an attacker to access local files.
if err != nil { if err != nil {
return nil, err return nil, err
} }
dbDSN := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8", "username", "password", "127.0.0.1", 3306, cfg.dsn) dbDSN := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8", "username", "password", "127.0.0.1", 3306, cfg.dsn)
db, _ := sql.Open("mysql", dbDSN) // $ Alert[go/dsn-injection-local] db, _ := sql.Open("mysql", dbDSN)
return db, nil return db, nil
} }

View File

@@ -1,4 +1,2 @@
query: experimental/CWE-74/DsnInjection.ql query: experimental/CWE-74/DsnInjection.ql
postprocess: postprocess: utils/test/PrettyPrintModels.ql
- utils/test/PrettyPrintModels.ql
- utils/test/InlineExpectationsTestQuery.ql

View File

@@ -1,4 +1,2 @@
query: experimental/CWE-74/DsnInjectionLocal.ql query: experimental/CWE-74/DsnInjectionLocal.ql
postprocess: postprocess: utils/test/PrettyPrintModels.ql
- utils/test/PrettyPrintModels.ql
- utils/test/InlineExpectationsTestQuery.ql

View File

@@ -1,2 +1 @@
query: experimental/CWE-807/SensitiveConditionBypass.ql experimental/CWE-807/SensitiveConditionBypass.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -4,7 +4,7 @@ import "net/http"
func example(w http.ResponseWriter, r *http.Request) { func example(w http.ResponseWriter, r *http.Request) {
test2 := "test" test2 := "test"
if r.Header.Get("X-Password") != test2 { // $ Alert if r.Header.Get("X-Password") != test2 {
login() login()
} }
} }

View File

@@ -13,7 +13,7 @@ const test = "localhost"
// Should alert as authkey is sensitive // Should alert as authkey is sensitive
func ex1(w http.ResponseWriter, r *http.Request) { func ex1(w http.ResponseWriter, r *http.Request) {
if r.Header.Get("Origin") != test { // $ Alert if r.Header.Get("Origin") != test {
authkey := "randomDatta" authkey := "randomDatta"
io.WriteString(w, authkey) io.WriteString(w, authkey)
} }
@@ -22,7 +22,7 @@ func ex1(w http.ResponseWriter, r *http.Request) {
// Should alert as authkey is sensitive // Should alert as authkey is sensitive
func ex2(w http.ResponseWriter, r *http.Request) { func ex2(w http.ResponseWriter, r *http.Request) {
test2 := "test" test2 := "test"
if r.Header.Get("Origin") != test2 { // $ Alert if r.Header.Get("Origin") != test2 {
authkey := "randomDatta2" authkey := "randomDatta2"
io.WriteString(w, authkey) io.WriteString(w, authkey)
} }
@@ -31,7 +31,7 @@ func ex2(w http.ResponseWriter, r *http.Request) {
// Should alert as login() is sensitive // Should alert as login() is sensitive
func ex3(w http.ResponseWriter, r *http.Request) { func ex3(w http.ResponseWriter, r *http.Request) {
test2 := "test" test2 := "test"
if r.Header.Get("Origin") != test2 { // $ Alert if r.Header.Get("Origin") != test2 {
login() login()
} }
} }

View File

@@ -1,2 +1 @@
query: experimental/CWE-840/ConditionalBypass.ql experimental/CWE-840/ConditionalBypass.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -6,7 +6,7 @@ import (
func exampleHandlerBad(w http.ResponseWriter, r *http.Request) { func exampleHandlerBad(w http.ResponseWriter, r *http.Request) {
// BAD: the Origin and Host headers are user controlled // BAD: the Origin and Host headers are user controlled
if r.Header.Get("Origin") != "http://"+r.Host { // $ Alert if r.Header.Get("Origin") != "http://"+r.Host {
//do something //do something
} }
} }

View File

@@ -6,14 +6,14 @@ import (
// BAD: taken from https://www.gorillatoolkit.org/pkg/websocket // BAD: taken from https://www.gorillatoolkit.org/pkg/websocket
func ex1(w http.ResponseWriter, r *http.Request) { func ex1(w http.ResponseWriter, r *http.Request) {
if r.Header.Get("Origin") != "http://"+r.Host { // $ Alert if r.Header.Get("Origin") != "http://"+r.Host {
//do something //do something
} }
} }
// BAD: both operands are from remote sources // BAD: both operands are from remote sources
func ex2(w http.ResponseWriter, r *http.Request) { func ex2(w http.ResponseWriter, r *http.Request) {
if r.Header.Get("Origin") != "http://"+r.Header.Get("Header") { // $ Alert if r.Header.Get("Origin") != "http://"+r.Header.Get("Header") {
//do something //do something
} }
} }

View File

@@ -5,7 +5,7 @@ import "os"
func openFiles(filenames []string) { func openFiles(filenames []string) {
for _, filename := range filenames { for _, filename := range filenames {
file, err := os.Open(filename) file, err := os.Open(filename)
defer file.Close() // $ Alert[go/examples/deferinloop] defer file.Close()
if err != nil { if err != nil {
// handle error // handle error
} }

View File

@@ -1,2 +1 @@
query: experimental/InconsistentCode/DeferInLoop.ql experimental/InconsistentCode/DeferInLoop.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -4,6 +4,6 @@ import "gorm.io/gorm"
func getUserId(db *gorm.DB, name string) int64 { func getUserId(db *gorm.DB, name string) int64 {
var user User var user User
db.Where("name = ?", name).First(&user) // $ Alert[go/examples/gorm-error-not-checked] db.Where("name = ?", name).First(&user)
return user.Id return user.Id
} }

View File

@@ -1,2 +1 @@
query: experimental/InconsistentCode/GORMErrorNotChecked.ql experimental/InconsistentCode/GORMErrorNotChecked.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -3,24 +3,24 @@ package main
func test() { func test() {
var xs []int var xs []int
for _ = range xs { for _ = range xs {
defer test() // $ Alert[go/examples/deferinloop] // not ok defer test() // not ok
} }
for _ = range xs { for _ = range xs {
if true { if true {
defer test() // $ Alert[go/examples/deferinloop] // not ok defer test() // not ok
} }
} }
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
defer test() // $ Alert[go/examples/deferinloop] defer test()
} }
for true { for true {
defer test() // $ Alert[go/examples/deferinloop] // not ok defer test() // not ok
} }
for false { for false {
defer test() // $ Alert[go/examples/deferinloop] // fine but caught defer test() // fine but caught
} }
} }

View File

@@ -1,15 +1,3 @@
#select
| WrongUsageOfUnsafe.go:77:16:77:55 | type conversion | WrongUsageOfUnsafe.go:77:27:77:54 | type conversion | WrongUsageOfUnsafe.go:77:16:77:55 | type conversion | $@. | WrongUsageOfUnsafe.go:77:27:77:54 | type conversion | Dangerous array type casting to [8]uint8 from an index expression ([8]uint8)[2] (the destination type is 2 elements longer) |
| WrongUsageOfUnsafe.go:111:16:111:59 | type conversion | WrongUsageOfUnsafe.go:111:31:111:58 | type conversion | WrongUsageOfUnsafe.go:111:16:111:59 | type conversion | $@. | WrongUsageOfUnsafe.go:111:31:111:58 | type conversion | Dangerous array type casting to [17]uint8 from an index expression ([8]uint8)[0] (the destination type is 9 elements longer) |
| WrongUsageOfUnsafe.go:129:16:129:56 | type conversion | WrongUsageOfUnsafe.go:129:31:129:55 | type conversion | WrongUsageOfUnsafe.go:129:16:129:56 | type conversion | $@. | WrongUsageOfUnsafe.go:129:31:129:55 | type conversion | Dangerous array type casting to [17]uint8 from [8]uint8 |
| WrongUsageOfUnsafe.go:149:16:149:56 | type conversion | WrongUsageOfUnsafe.go:149:31:149:55 | type conversion | WrongUsageOfUnsafe.go:149:16:149:56 | type conversion | $@. | WrongUsageOfUnsafe.go:149:31:149:55 | type conversion | Dangerous array type casting to [17]uint8 from [8]uint8 |
| WrongUsageOfUnsafe.go:166:16:166:58 | type conversion | WrongUsageOfUnsafe.go:166:33:166:57 | type conversion | WrongUsageOfUnsafe.go:166:16:166:58 | type conversion | $@. | WrongUsageOfUnsafe.go:166:33:166:57 | type conversion | Dangerous array type casting to [17]string from [8]string |
| WrongUsageOfUnsafe.go:189:16:189:56 | type conversion | WrongUsageOfUnsafe.go:189:31:189:55 | type conversion | WrongUsageOfUnsafe.go:189:16:189:56 | type conversion | $@. | WrongUsageOfUnsafe.go:189:31:189:55 | type conversion | Dangerous type up-casting to [17]uint8 from struct type |
| WrongUsageOfUnsafe.go:211:16:211:61 | type conversion | WrongUsageOfUnsafe.go:211:31:211:60 | type conversion | WrongUsageOfUnsafe.go:211:16:211:61 | type conversion | $@. | WrongUsageOfUnsafe.go:211:31:211:60 | type conversion | Dangerous array type casting to [17]uint8 from [8]uint8 |
| WrongUsageOfUnsafe.go:243:9:243:27 | type conversion | WrongUsageOfUnsafe.go:227:31:227:55 | type conversion | WrongUsageOfUnsafe.go:243:9:243:27 | type conversion | $@. | WrongUsageOfUnsafe.go:227:31:227:55 | type conversion | Dangerous array type casting to [17]uint8 from [8]uint8 |
| WrongUsageOfUnsafe.go:256:16:256:53 | type conversion | WrongUsageOfUnsafe.go:256:28:256:52 | type conversion | WrongUsageOfUnsafe.go:256:16:256:53 | type conversion | $@. | WrongUsageOfUnsafe.go:256:28:256:52 | type conversion | Dangerous array type casting to [4]int64 from [1]int64 |
| WrongUsageOfUnsafe.go:274:16:274:50 | type conversion | WrongUsageOfUnsafe.go:274:25:274:49 | type conversion | WrongUsageOfUnsafe.go:274:16:274:50 | type conversion | $@. | WrongUsageOfUnsafe.go:274:25:274:49 | type conversion | Dangerous numeric type casting to int64 from int8 |
| WrongUsageOfUnsafe.go:292:16:292:48 | type conversion | WrongUsageOfUnsafe.go:292:23:292:47 | type conversion | WrongUsageOfUnsafe.go:292:16:292:48 | type conversion | $@. | WrongUsageOfUnsafe.go:292:23:292:47 | type conversion | Dangerous numeric type casting to int from int8 |
edges edges
| WrongUsageOfUnsafe.go:17:24:17:48 | type conversion | WrongUsageOfUnsafe.go:17:13:17:49 | type conversion | provenance | | | WrongUsageOfUnsafe.go:17:24:17:48 | type conversion | WrongUsageOfUnsafe.go:17:13:17:49 | type conversion | provenance | |
| WrongUsageOfUnsafe.go:34:24:34:51 | type conversion | WrongUsageOfUnsafe.go:34:13:34:52 | type conversion | provenance | | | WrongUsageOfUnsafe.go:34:24:34:51 | type conversion | WrongUsageOfUnsafe.go:34:13:34:52 | type conversion | provenance | |
@@ -60,3 +48,15 @@ nodes
| WrongUsageOfUnsafe.go:292:16:292:48 | type conversion | semmle.label | type conversion | | WrongUsageOfUnsafe.go:292:16:292:48 | type conversion | semmle.label | type conversion |
| WrongUsageOfUnsafe.go:292:23:292:47 | type conversion | semmle.label | type conversion | | WrongUsageOfUnsafe.go:292:23:292:47 | type conversion | semmle.label | type conversion |
subpaths subpaths
#select
| WrongUsageOfUnsafe.go:77:16:77:55 | type conversion | WrongUsageOfUnsafe.go:77:27:77:54 | type conversion | WrongUsageOfUnsafe.go:77:16:77:55 | type conversion | $@. | WrongUsageOfUnsafe.go:77:27:77:54 | type conversion | Dangerous array type casting to [8]uint8 from an index expression ([8]uint8)[2] (the destination type is 2 elements longer) |
| WrongUsageOfUnsafe.go:111:16:111:59 | type conversion | WrongUsageOfUnsafe.go:111:31:111:58 | type conversion | WrongUsageOfUnsafe.go:111:16:111:59 | type conversion | $@. | WrongUsageOfUnsafe.go:111:31:111:58 | type conversion | Dangerous array type casting to [17]uint8 from an index expression ([8]uint8)[0] (the destination type is 9 elements longer) |
| WrongUsageOfUnsafe.go:129:16:129:56 | type conversion | WrongUsageOfUnsafe.go:129:31:129:55 | type conversion | WrongUsageOfUnsafe.go:129:16:129:56 | type conversion | $@. | WrongUsageOfUnsafe.go:129:31:129:55 | type conversion | Dangerous array type casting to [17]uint8 from [8]uint8 |
| WrongUsageOfUnsafe.go:149:16:149:56 | type conversion | WrongUsageOfUnsafe.go:149:31:149:55 | type conversion | WrongUsageOfUnsafe.go:149:16:149:56 | type conversion | $@. | WrongUsageOfUnsafe.go:149:31:149:55 | type conversion | Dangerous array type casting to [17]uint8 from [8]uint8 |
| WrongUsageOfUnsafe.go:166:16:166:58 | type conversion | WrongUsageOfUnsafe.go:166:33:166:57 | type conversion | WrongUsageOfUnsafe.go:166:16:166:58 | type conversion | $@. | WrongUsageOfUnsafe.go:166:33:166:57 | type conversion | Dangerous array type casting to [17]string from [8]string |
| WrongUsageOfUnsafe.go:189:16:189:56 | type conversion | WrongUsageOfUnsafe.go:189:31:189:55 | type conversion | WrongUsageOfUnsafe.go:189:16:189:56 | type conversion | $@. | WrongUsageOfUnsafe.go:189:31:189:55 | type conversion | Dangerous type up-casting to [17]uint8 from struct type |
| WrongUsageOfUnsafe.go:211:16:211:61 | type conversion | WrongUsageOfUnsafe.go:211:31:211:60 | type conversion | WrongUsageOfUnsafe.go:211:16:211:61 | type conversion | $@. | WrongUsageOfUnsafe.go:211:31:211:60 | type conversion | Dangerous array type casting to [17]uint8 from [8]uint8 |
| WrongUsageOfUnsafe.go:243:9:243:27 | type conversion | WrongUsageOfUnsafe.go:227:31:227:55 | type conversion | WrongUsageOfUnsafe.go:243:9:243:27 | type conversion | $@. | WrongUsageOfUnsafe.go:227:31:227:55 | type conversion | Dangerous array type casting to [17]uint8 from [8]uint8 |
| WrongUsageOfUnsafe.go:256:16:256:53 | type conversion | WrongUsageOfUnsafe.go:256:28:256:52 | type conversion | WrongUsageOfUnsafe.go:256:16:256:53 | type conversion | $@. | WrongUsageOfUnsafe.go:256:28:256:52 | type conversion | Dangerous array type casting to [4]int64 from [1]int64 |
| WrongUsageOfUnsafe.go:274:16:274:50 | type conversion | WrongUsageOfUnsafe.go:274:25:274:49 | type conversion | WrongUsageOfUnsafe.go:274:16:274:50 | type conversion | $@. | WrongUsageOfUnsafe.go:274:25:274:49 | type conversion | Dangerous numeric type casting to int64 from int8 |
| WrongUsageOfUnsafe.go:292:16:292:48 | type conversion | WrongUsageOfUnsafe.go:292:23:292:47 | type conversion | WrongUsageOfUnsafe.go:292:16:292:48 | type conversion | $@. | WrongUsageOfUnsafe.go:292:23:292:47 | type conversion | Dangerous numeric type casting to int from int8 |

View File

@@ -74,7 +74,7 @@ func badIndexExpr() {
// the address of the 3rd element of the `harmless` array, // the address of the 3rd element of the `harmless` array,
// and continue for 8 bytes, going out of the boundaries of // and continue for 8 bytes, going out of the boundaries of
// `harmless` and crossing into the memory occupied by `secret`. // `harmless` and crossing into the memory occupied by `secret`.
var leaking = (*[8]byte)(unsafe.Pointer(&harmless[2])) // $ Alert // BAD var leaking = (*[8]byte)(unsafe.Pointer(&harmless[2])) // BAD
fmt.Println(string((*leaking)[:])) fmt.Println(string((*leaking)[:]))
@@ -108,7 +108,7 @@ func bad0() {
// Read before secret, overflowing into secret // Read before secret, overflowing into secret
// (notice we get the pointer to the first byte of harmless) // (notice we get the pointer to the first byte of harmless)
var leaking = (*[8 + 9]byte)(unsafe.Pointer(&harmless[0])) // $ Alert // BAD var leaking = (*[8 + 9]byte)(unsafe.Pointer(&harmless[0])) // BAD
fmt.Println(string((*leaking)[:])) fmt.Println(string((*leaking)[:]))
@@ -126,7 +126,7 @@ func bad1() {
// Read before secret, overflowing into secret // Read before secret, overflowing into secret
// (notice we read more than the length of harmless) // (notice we read more than the length of harmless)
var leaking = (*[8 + 9]byte)(unsafe.Pointer(&harmless)) // $ Alert // BAD var leaking = (*[8 + 9]byte)(unsafe.Pointer(&harmless)) // BAD
fmt.Println(string((*leaking)[:])) fmt.Println(string((*leaking)[:]))
@@ -146,7 +146,7 @@ func bad2() {
// Read before secret, overflowing into secret // Read before secret, overflowing into secret
// (notice we read more than the length of harmless) // (notice we read more than the length of harmless)
var leaking = (*[8 + 9]byte)(unsafe.Pointer(&harmless)) // $ Alert // BAD var leaking = (*[8 + 9]byte)(unsafe.Pointer(&harmless)) // BAD
fmt.Println(string((*leaking)[:])) fmt.Println(string((*leaking)[:]))
@@ -163,7 +163,7 @@ func bad3() {
// Read before secret, overflowing into secret // Read before secret, overflowing into secret
// (notice we read more than the length of harmless) // (notice we read more than the length of harmless)
var leaking = (*[8 + 9]string)(unsafe.Pointer(&harmless)) // $ Alert // BAD var leaking = (*[8 + 9]string)(unsafe.Pointer(&harmless)) // BAD
fmt.Println(*leaking) fmt.Println(*leaking)
fmt.Println([17]string((*leaking))) fmt.Println([17]string((*leaking)))
@@ -186,7 +186,7 @@ func bad4() {
// Read before secret, overflowing into secret // Read before secret, overflowing into secret
// (notice we read more than the length of harmless) // (notice we read more than the length of harmless)
var leaking = (*[8 + 9]byte)(unsafe.Pointer(&harmless)) // $ Alert // BAD var leaking = (*[8 + 9]byte)(unsafe.Pointer(&harmless)) // BAD
fmt.Println(string((*leaking)[:])) fmt.Println(string((*leaking)[:]))
@@ -208,7 +208,7 @@ func bad5() {
// Read before secret, overflowing into secret // Read before secret, overflowing into secret
// (notice we read more than the length of harmless) // (notice we read more than the length of harmless)
var leaking = (*[8 + 9]byte)(unsafe.Pointer(&harmless.Data)) // $ Alert // BAD var leaking = (*[8 + 9]byte)(unsafe.Pointer(&harmless.Data)) // BAD
fmt.Println(string(leaking[:])) fmt.Println(string(leaking[:]))
@@ -224,7 +224,7 @@ func bad6() {
secret := [9]byte{'s', 'e', 'n', 's', 'i', 't', 'i', 'v', 'e'} secret := [9]byte{'s', 'e', 'n', 's', 'i', 't', 'i', 'v', 'e'}
// Read before secret: // Read before secret:
var leaking = buffer_request(unsafe.Pointer(&harmless)) // $ Source // BAD (see inside buffer_request func) var leaking = buffer_request(unsafe.Pointer(&harmless)) // BAD (see inside buffer_request func)
fmt.Println((string)(leaking[:])) fmt.Println((string)(leaking[:]))
@@ -240,7 +240,7 @@ func buffer_request(req unsafe.Pointer) [8 + 9]byte {
// will be read, the read will also contain pieces of // will be read, the read will also contain pieces of
// data from `secret`. // data from `secret`.
var buf [8 + 9]byte var buf [8 + 9]byte
buf = *(*[8 + 9]byte)(req) // $ Alert // BAD (from above func) buf = *(*[8 + 9]byte)(req) // BAD (from above func)
return buf return buf
} }
func bad7() { func bad7() {
@@ -253,7 +253,7 @@ func bad7() {
// (notice we read more than the length of harmless); // (notice we read more than the length of harmless);
// the leaking array will not contain letters, // the leaking array will not contain letters,
// but integers representing bytes from `secret`. // but integers representing bytes from `secret`.
var leaking = (*[4]int64)(unsafe.Pointer(&harmless)) // $ Alert // BAD var leaking = (*[4]int64)(unsafe.Pointer(&harmless)) // BAD
fmt.Println(*leaking) fmt.Println(*leaking)
@@ -271,7 +271,7 @@ func bad8() {
// Read before secret, overflowing into secret // Read before secret, overflowing into secret
// (notice we read more than the length of harmless); // (notice we read more than the length of harmless);
// the leaking data will contain some bits from `secret`. // the leaking data will contain some bits from `secret`.
var leaking = (*int64)(unsafe.Pointer(&harmless)) // $ Alert // BAD var leaking = (*int64)(unsafe.Pointer(&harmless)) // BAD
fmt.Println(*leaking) fmt.Println(*leaking)
@@ -289,7 +289,7 @@ func bad9() {
// Read before secret, overflowing into secret // Read before secret, overflowing into secret
// (notice we read more than the length of harmless); // (notice we read more than the length of harmless);
// the leaking data will contain some bits from `secret`. // the leaking data will contain some bits from `secret`.
var leaking = (*int)(unsafe.Pointer(&harmless)) // $ Alert // BAD var leaking = (*int)(unsafe.Pointer(&harmless)) // BAD
fmt.Println(*leaking) fmt.Println(*leaking)

View File

@@ -1,2 +1 @@
query: experimental/Unsafe/WrongUsageOfUnsafe.ql experimental/Unsafe/WrongUsageOfUnsafe.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -1,4 +1,2 @@
query: Security/CWE-089/SqlInjection.ql query: Security/CWE-089/SqlInjection.ql
postprocess: postprocess: utils/test/PrettyPrintModels.ql
- utils/test/PrettyPrintModels.ql
- utils/test/InlineExpectationsTestQuery.ql

View File

@@ -1,4 +1,2 @@
query: Security/CWE-079/StoredXss.ql query: Security/CWE-079/StoredXss.ql
postprocess: postprocess: utils/test/PrettyPrintModels.ql
- utils/test/PrettyPrintModels.ql
- utils/test/InlineExpectationsTestQuery.ql

View File

@@ -8,61 +8,61 @@ import (
// BAD: using untrusted data in SQL queries // BAD: using untrusted data in SQL queries
func testDbMethods(bdb *orm.DB, untrustedSource *http.Request) { func testDbMethods(bdb *orm.DB, untrustedSource *http.Request) {
untrusted := untrustedSource.UserAgent() // $ Source[go/sql-injection] untrusted := untrustedSource.UserAgent()
bdb.Exec(untrusted) // $ querystring=untrusted Alert[go/sql-injection] bdb.Exec(untrusted) // $ querystring=untrusted
bdb.ExecContext(nil, untrusted) // $ querystring=untrusted Alert[go/sql-injection] bdb.ExecContext(nil, untrusted) // $ querystring=untrusted
bdb.Prepare(untrusted) // $ querystring=untrusted Alert[go/sql-injection] bdb.Prepare(untrusted) // $ querystring=untrusted
bdb.PrepareContext(nil, untrusted) // $ querystring=untrusted Alert[go/sql-injection] bdb.PrepareContext(nil, untrusted) // $ querystring=untrusted
bdb.Query(untrusted) // $ querystring=untrusted Alert[go/sql-injection] bdb.Query(untrusted) // $ querystring=untrusted
bdb.QueryContext(nil, untrusted) // $ querystring=untrusted Alert[go/sql-injection] bdb.QueryContext(nil, untrusted) // $ querystring=untrusted
bdb.QueryRow(untrusted) // $ querystring=untrusted Alert[go/sql-injection] bdb.QueryRow(untrusted) // $ querystring=untrusted
bdb.QueryRowContext(nil, untrusted) // $ querystring=untrusted Alert[go/sql-injection] bdb.QueryRowContext(nil, untrusted) // $ querystring=untrusted
} }
// BAD: using untrusted data to build SQL queries (QueryBuilder does not sanitize its arguments) // BAD: using untrusted data to build SQL queries (QueryBuilder does not sanitize its arguments)
func testQueryBuilderMethods(qb orm.QueryBuilder, untrustedSource *http.Request) { func testQueryBuilderMethods(qb orm.QueryBuilder, untrustedSource *http.Request) {
untrusted := untrustedSource.UserAgent() // $ Source[go/sql-injection] untrusted := untrustedSource.UserAgent()
untrusted2 := untrustedSource.UserAgent() // $ Source[go/sql-injection] untrusted2 := untrustedSource.UserAgent()
qb.Select(untrusted) // $ querystring=untrusted Alert[go/sql-injection] qb.Select(untrusted) // $ querystring=untrusted
qb.From(untrusted) // $ querystring=untrusted Alert[go/sql-injection] qb.From(untrusted) // $ querystring=untrusted
qb.InnerJoin(untrusted) // $ querystring=untrusted Alert[go/sql-injection] qb.InnerJoin(untrusted) // $ querystring=untrusted
qb.LeftJoin(untrusted) // $ querystring=untrusted Alert[go/sql-injection] qb.LeftJoin(untrusted) // $ querystring=untrusted
qb.RightJoin(untrusted) // $ querystring=untrusted Alert[go/sql-injection] qb.RightJoin(untrusted) // $ querystring=untrusted
qb.On(untrusted) // $ querystring=untrusted Alert[go/sql-injection] qb.On(untrusted) // $ querystring=untrusted
qb.Where(untrusted) // $ querystring=untrusted Alert[go/sql-injection] qb.Where(untrusted) // $ querystring=untrusted
qb.And(untrusted) // $ querystring=untrusted Alert[go/sql-injection] qb.And(untrusted) // $ querystring=untrusted
qb.Or(untrusted) // $ querystring=untrusted Alert[go/sql-injection] qb.Or(untrusted) // $ querystring=untrusted
qb.In(untrusted) // $ querystring=untrusted Alert[go/sql-injection] qb.In(untrusted) // $ querystring=untrusted
qb.OrderBy(untrusted) // $ querystring=untrusted Alert[go/sql-injection] qb.OrderBy(untrusted) // $ querystring=untrusted
qb.GroupBy(untrusted) // $ querystring=untrusted Alert[go/sql-injection] qb.GroupBy(untrusted) // $ querystring=untrusted
qb.Having(untrusted) // $ querystring=untrusted Alert[go/sql-injection] qb.Having(untrusted) // $ querystring=untrusted
qb.Update(untrusted) // $ querystring=untrusted Alert[go/sql-injection] qb.Update(untrusted) // $ querystring=untrusted
qb.Set(untrusted) // $ querystring=untrusted Alert[go/sql-injection] qb.Set(untrusted) // $ querystring=untrusted
qb.Delete(untrusted) // $ querystring=untrusted Alert[go/sql-injection] qb.Delete(untrusted) // $ querystring=untrusted
qb.InsertInto(untrusted, untrusted2) // $ querystring=untrusted querystring=untrusted2 Alert[go/sql-injection] qb.InsertInto(untrusted, untrusted2) // $ querystring=untrusted querystring=untrusted2
qb.Values(untrusted) // $ querystring=untrusted Alert[go/sql-injection] qb.Values(untrusted) // $ querystring=untrusted
qb.Subquery(untrusted, untrusted2) // $ querystring=untrusted querystring=untrusted2 Alert[go/sql-injection] qb.Subquery(untrusted, untrusted2) // $ querystring=untrusted querystring=untrusted2
} }
func testOrmerRaw(ormer orm.Ormer, untrustedSource *http.Request) { func testOrmerRaw(ormer orm.Ormer, untrustedSource *http.Request) {
untrusted := untrustedSource.UserAgent() // $ Source[go/sql-injection] untrusted := untrustedSource.UserAgent()
untrusted2 := untrustedSource.UserAgent() untrusted2 := untrustedSource.UserAgent()
ormer.Raw(untrusted, untrusted2) // $ querystring=untrusted Alert[go/sql-injection] // BAD: using an untrusted string as a query ormer.Raw(untrusted, untrusted2) // $ querystring=untrusted // BAD: using an untrusted string as a query
ormer.Raw("FROM ? SELECT ?", untrusted, untrusted2) // $ querystring="FROM ? SELECT ?" // GOOD: untrusted string used in argument context ormer.Raw("FROM ? SELECT ?", untrusted, untrusted2) // $ querystring="FROM ? SELECT ?" // GOOD: untrusted string used in argument context
} }
func testFilterRaw(querySeter orm.QuerySeter, untrustedSource *http.Request) { func testFilterRaw(querySeter orm.QuerySeter, untrustedSource *http.Request) {
untrusted := untrustedSource.UserAgent() // $ Source[go/sql-injection] untrusted := untrustedSource.UserAgent()
querySeter.FilterRaw(untrusted, "safe") // $ querystring="safe" // GOOD: untrusted used as a column name querySeter.FilterRaw(untrusted, "safe") // $ querystring="safe" // GOOD: untrusted used as a column name
querySeter.FilterRaw("safe", untrusted) // $ querystring=untrusted Alert[go/sql-injection] // BAD: untrusted used as a SQL fragment querySeter.FilterRaw("safe", untrusted) // $ querystring=untrusted // BAD: untrusted used as a SQL fragment
} }
func testConditionRaw(cond orm.Condition, untrustedSource *http.Request) { func testConditionRaw(cond orm.Condition, untrustedSource *http.Request) {
untrusted := untrustedSource.UserAgent() // $ Source[go/sql-injection] untrusted := untrustedSource.UserAgent()
cond.Raw(untrusted, "safe") // $ querystring="safe" // GOOD: untrusted used as a column name cond.Raw(untrusted, "safe") // $ querystring="safe" // GOOD: untrusted used as a column name
cond.Raw("safe", untrusted) // $ querystring=untrusted Alert[go/sql-injection] // BAD: untrusted used as a SQL fragment cond.Raw("safe", untrusted) // $ querystring=untrusted // BAD: untrusted used as a SQL fragment
} }
type SubStruct struct { type SubStruct struct {
@@ -77,90 +77,90 @@ type MyStruct struct {
// BAD: (possible stored XSS) retrieving data from a database then writing to an HTTP response // BAD: (possible stored XSS) retrieving data from a database then writing to an HTTP response
func testOrmerReads(ormer orm.Ormer, sink http.ResponseWriter) { func testOrmerReads(ormer orm.Ormer, sink http.ResponseWriter) {
obj := MyStruct{} obj := MyStruct{}
ormer.Read(&obj) // $ Source[go/stored-xss] ormer.Read(&obj)
sink.Write([]byte(obj.field)) // $ Alert[go/stored-xss] sink.Write([]byte(obj.field))
sink.Write([]byte(obj.substructs[0].field)) // $ Alert[go/stored-xss] sink.Write([]byte(obj.substructs[0].field))
obj2 := MyStruct{} obj2 := MyStruct{}
ormer.ReadForUpdate(&obj2) // $ Source[go/stored-xss] ormer.ReadForUpdate(&obj2)
sink.Write([]byte(obj2.field)) // $ Alert[go/stored-xss] sink.Write([]byte(obj2.field))
obj3 := MyStruct{} obj3 := MyStruct{}
ormer.ReadOrCreate(&obj3, "arg") // $ Source[go/stored-xss] ormer.ReadOrCreate(&obj3, "arg")
sink.Write([]byte(obj3.field)) // $ Alert[go/stored-xss] sink.Write([]byte(obj3.field))
} }
// BAD: (possible stored XSS) retrieving data from a database then writing to an HTTP response // BAD: (possible stored XSS) retrieving data from a database then writing to an HTTP response
func testFieldReads(textField *orm.TextField, jsonField *orm.JSONField, jsonbField *orm.JsonbField, sink http.ResponseWriter) { func testFieldReads(textField *orm.TextField, jsonField *orm.JSONField, jsonbField *orm.JsonbField, sink http.ResponseWriter) {
sink.Write([]byte(textField.Value())) // $ Alert[go/stored-xss] sink.Write([]byte(textField.Value()))
sink.Write([]byte(textField.RawValue().(string))) // $ Alert[go/stored-xss] sink.Write([]byte(textField.RawValue().(string)))
sink.Write([]byte(textField.String())) // $ Alert[go/stored-xss] sink.Write([]byte(textField.String()))
sink.Write([]byte(jsonField.Value())) // $ Alert[go/stored-xss] sink.Write([]byte(jsonField.Value()))
sink.Write([]byte(jsonField.RawValue().(string))) // $ Alert[go/stored-xss] sink.Write([]byte(jsonField.RawValue().(string)))
sink.Write([]byte(jsonField.String())) // $ Alert[go/stored-xss] sink.Write([]byte(jsonField.String()))
sink.Write([]byte(jsonbField.Value())) // $ Alert[go/stored-xss] sink.Write([]byte(jsonbField.Value()))
sink.Write([]byte(jsonbField.RawValue().(string))) // $ Alert[go/stored-xss] sink.Write([]byte(jsonbField.RawValue().(string)))
sink.Write([]byte(jsonbField.String())) // $ Alert[go/stored-xss] sink.Write([]byte(jsonbField.String()))
} }
// BAD: (possible stored XSS) retrieving data from a database then writing to an HTTP response // BAD: (possible stored XSS) retrieving data from a database then writing to an HTTP response
func testQuerySeterReads(qs orm.QuerySeter, sink http.ResponseWriter) { func testQuerySeterReads(qs orm.QuerySeter, sink http.ResponseWriter) {
var objs []*MyStruct var objs []*MyStruct
qs.All(&objs) // $ Source[go/stored-xss] qs.All(&objs)
sink.Write([]byte(objs[0].field)) // $ Alert[go/stored-xss] sink.Write([]byte(objs[0].field))
var obj MyStruct var obj MyStruct
qs.One(&obj) // $ Source[go/stored-xss] qs.One(&obj)
sink.Write([]byte(obj.field)) // $ Alert[go/stored-xss] sink.Write([]byte(obj.field))
var allMaps []orm.Params var allMaps []orm.Params
qs.Values(&allMaps) // $ Source[go/stored-xss] qs.Values(&allMaps)
sink.Write([]byte(allMaps[0]["field"].(string))) // $ Alert[go/stored-xss] sink.Write([]byte(allMaps[0]["field"].(string)))
var allLists []orm.ParamsList var allLists []orm.ParamsList
qs.ValuesList(&allLists) // $ Source[go/stored-xss] qs.ValuesList(&allLists)
sink.Write([]byte(allLists[0][0].(string))) // $ Alert[go/stored-xss] sink.Write([]byte(allLists[0][0].(string)))
var oneList orm.ParamsList var oneList orm.ParamsList
qs.ValuesFlat(&oneList, "colname") // $ Source[go/stored-xss] qs.ValuesFlat(&oneList, "colname")
sink.Write([]byte(oneList[0].(string))) // $ Alert[go/stored-xss] sink.Write([]byte(oneList[0].(string)))
var oneRowMap orm.Params var oneRowMap orm.Params
qs.RowsToMap(&oneRowMap, "key", "value") // $ Source[go/stored-xss] qs.RowsToMap(&oneRowMap, "key", "value")
sink.Write([]byte(oneRowMap["field"].(string))) // $ Alert[go/stored-xss] sink.Write([]byte(oneRowMap["field"].(string)))
var oneRowStruct MyStruct var oneRowStruct MyStruct
qs.RowsToStruct(&oneRowStruct, "key", "value") // $ Source[go/stored-xss] qs.RowsToStruct(&oneRowStruct, "key", "value")
sink.Write([]byte(oneRowStruct.field)) // $ Alert[go/stored-xss] sink.Write([]byte(oneRowStruct.field))
} }
// BAD: (possible stored XSS) retrieving data from a database then writing to an HTTP response // BAD: (possible stored XSS) retrieving data from a database then writing to an HTTP response
func testRawSeterReads(rs orm.RawSeter, sink http.ResponseWriter) { func testRawSeterReads(rs orm.RawSeter, sink http.ResponseWriter) {
var allMaps []orm.Params var allMaps []orm.Params
rs.Values(&allMaps) // $ Source[go/stored-xss] rs.Values(&allMaps)
sink.Write([]byte(allMaps[0]["field"].(string))) // $ Alert[go/stored-xss] sink.Write([]byte(allMaps[0]["field"].(string)))
var allLists []orm.ParamsList var allLists []orm.ParamsList
rs.ValuesList(&allLists) // $ Source[go/stored-xss] rs.ValuesList(&allLists)
sink.Write([]byte(allLists[0][0].(string))) // $ Alert[go/stored-xss] sink.Write([]byte(allLists[0][0].(string)))
var oneList orm.ParamsList var oneList orm.ParamsList
rs.ValuesFlat(&oneList, "colname") // $ Source[go/stored-xss] rs.ValuesFlat(&oneList, "colname")
sink.Write([]byte(oneList[0].(string))) // $ Alert[go/stored-xss] sink.Write([]byte(oneList[0].(string)))
var oneRowMap orm.Params var oneRowMap orm.Params
rs.RowsToMap(&oneRowMap, "key", "value") // $ Source[go/stored-xss] rs.RowsToMap(&oneRowMap, "key", "value")
sink.Write([]byte(oneRowMap["field"].(string))) // $ Alert[go/stored-xss] sink.Write([]byte(oneRowMap["field"].(string)))
var oneRowStruct MyStruct var oneRowStruct MyStruct
rs.RowsToStruct(&oneRowStruct, "key", "value") // $ Source[go/stored-xss] rs.RowsToStruct(&oneRowStruct, "key", "value")
sink.Write([]byte(oneRowStruct.field)) // $ Alert[go/stored-xss] sink.Write([]byte(oneRowStruct.field))
var strField string var strField string
rs.QueryRow(&strField) // $ Source[go/stored-xss] rs.QueryRow(&strField)
sink.Write([]byte(strField)) // $ Alert[go/stored-xss] sink.Write([]byte(strField))
var strFields []string var strFields []string
rs.QueryRows(&strFields) // $ Source[go/stored-xss] rs.QueryRows(&strFields)
sink.Write([]byte(strFields[0])) // $ Alert[go/stored-xss] sink.Write([]byte(strFields[0]))
} }

View File

@@ -1,4 +1,2 @@
query: Security/CWE-079/ReflectedXss.ql query: Security/CWE-079/ReflectedXss.ql
postprocess: postprocess: utils/test/PrettyPrintModels.ql
- utils/test/PrettyPrintModels.ql
- utils/test/InlineExpectationsTestQuery.ql

View File

@@ -10,7 +10,7 @@ var hidden string
func hideUserData(next http.Handler) http.Handler { func hideUserData(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
hidden = r.URL.Path // $ Source hidden = r.URL.Path
next.ServeHTTP(w, r) next.ServeHTTP(w, r)
}) })
} }
@@ -18,10 +18,10 @@ func hideUserData(next http.Handler) http.Handler {
func main() { func main() {
r := chi.NewRouter() r := chi.NewRouter()
r.With(hideUserData).Get("/", func(w http.ResponseWriter, r *http.Request) { r.With(hideUserData).Get("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(hidden)) // $ Alert w.Write([]byte(hidden))
w.Write([]byte(chi.URLParam(r, "someParam"))) // $ Alert w.Write([]byte(chi.URLParam(r, "someParam")))
w.Write([]byte(chi.URLParamFromCtx(r.Context(), "someKey"))) // $ Alert w.Write([]byte(chi.URLParamFromCtx(r.Context(), "someKey")))
w.Write([]byte(chi.RouteContext(r.Context()).URLParam("someOtherKey"))) // $ Alert w.Write([]byte(chi.RouteContext(r.Context()).URLParam("someOtherKey")))
}) })
http.ListenAndServe(":3000", r) http.ListenAndServe(":3000", r)
} }

View File

@@ -1,4 +1,2 @@
query: Security/CWE-601/OpenUrlRedirect.ql query: Security/CWE-601/OpenUrlRedirect.ql
postprocess: postprocess: utils/test/PrettyPrintModels.ql
- utils/test/PrettyPrintModels.ql
- utils/test/InlineExpectationsTestQuery.ql

View File

@@ -1,4 +1,2 @@
query: Security/CWE-079/ReflectedXss.ql query: Security/CWE-079/ReflectedXss.ql
postprocess: postprocess: utils/test/PrettyPrintModels.ql
- utils/test/PrettyPrintModels.ql
- utils/test/InlineExpectationsTestQuery.ql

View File

@@ -1,4 +1,2 @@
query: Security/CWE-022/TaintedPath.ql query: Security/CWE-022/TaintedPath.ql
postprocess: postprocess: utils/test/PrettyPrintModels.ql
- utils/test/PrettyPrintModels.ql
- utils/test/InlineExpectationsTestQuery.ql

View File

@@ -12,81 +12,81 @@ import (
// All are XSS vulnerabilities, except as specifically noted. // All are XSS vulnerabilities, except as specifically noted.
func testParam(ctx echo.Context) error { func testParam(ctx echo.Context) error {
param := ctx.Param("someParam") // $ Source[go/reflected-xss] param := ctx.Param("someParam")
ctx.HTML(200, param) // $ Alert[go/reflected-xss] ctx.HTML(200, param)
return nil return nil
} }
func testParamValues(ctx echo.Context) error { func testParamValues(ctx echo.Context) error {
param := ctx.ParamValues()[0] // $ Source[go/reflected-xss] param := ctx.ParamValues()[0]
ctx.HTML(200, param) // $ Alert[go/reflected-xss] ctx.HTML(200, param)
return nil return nil
} }
func testQueryParam(ctx echo.Context) error { func testQueryParam(ctx echo.Context) error {
param := ctx.QueryParam("someParam") // $ Source[go/reflected-xss] param := ctx.QueryParam("someParam")
ctx.HTML(200, param) // $ Alert[go/reflected-xss] ctx.HTML(200, param)
return nil return nil
} }
func testQueryParams(ctx echo.Context) error { func testQueryParams(ctx echo.Context) error {
param := ctx.QueryParams()["someParam"][0] // $ Source[go/reflected-xss] param := ctx.QueryParams()["someParam"][0]
ctx.HTML(200, param) // $ Alert[go/reflected-xss] ctx.HTML(200, param)
return nil return nil
} }
func testQueryString(ctx echo.Context) error { func testQueryString(ctx echo.Context) error {
qstr := ctx.QueryString() // $ Source[go/reflected-xss] qstr := ctx.QueryString()
ctx.HTML(200, qstr) // $ Alert[go/reflected-xss] ctx.HTML(200, qstr)
return nil return nil
} }
func testFormValue(ctx echo.Context) error { func testFormValue(ctx echo.Context) error {
val := ctx.FormValue("someField") // $ Source[go/reflected-xss] val := ctx.FormValue("someField")
ctx.HTML(200, val) // $ Alert[go/reflected-xss] ctx.HTML(200, val)
return nil return nil
} }
func testFormParams(ctx echo.Context) error { func testFormParams(ctx echo.Context) error {
params, _ := ctx.FormParams() // $ Source[go/reflected-xss] params, _ := ctx.FormParams()
ctx.HTML(200, params["someField"][0]) // $ Alert[go/reflected-xss] ctx.HTML(200, params["someField"][0])
return nil return nil
} }
func testFormFile(ctx echo.Context) error { func testFormFile(ctx echo.Context) error {
fileHeader, _ := ctx.FormFile("someFilename") // $ Source[go/reflected-xss] fileHeader, _ := ctx.FormFile("someFilename")
file, _ := fileHeader.Open() file, _ := fileHeader.Open()
buffer := make([]byte, 100) buffer := make([]byte, 100)
file.Read(buffer) file.Read(buffer)
ctx.HTMLBlob(200, buffer) // $ Alert[go/reflected-xss] ctx.HTMLBlob(200, buffer)
return nil return nil
} }
func testMultipartFormValue(ctx echo.Context) error { func testMultipartFormValue(ctx echo.Context) error {
form, _ := ctx.MultipartForm() // $ Source[go/reflected-xss] form, _ := ctx.MultipartForm()
ctx.HTML(200, form.Value["someField"][0]) // $ Alert[go/reflected-xss] ctx.HTML(200, form.Value["someField"][0])
return nil return nil
} }
func testMultipartFormFile(ctx echo.Context) error { func testMultipartFormFile(ctx echo.Context) error {
form, _ := ctx.MultipartForm() // $ Source[go/reflected-xss] form, _ := ctx.MultipartForm()
fileHeader := form.File["someFilename"][0] fileHeader := form.File["someFilename"][0]
file, _ := fileHeader.Open() file, _ := fileHeader.Open()
buffer := make([]byte, 100) buffer := make([]byte, 100)
file.Read(buffer) file.Read(buffer)
ctx.HTMLBlob(200, buffer) // $ Alert[go/reflected-xss] ctx.HTMLBlob(200, buffer)
return nil return nil
} }
func testCookie(ctx echo.Context) error { func testCookie(ctx echo.Context) error {
val, _ := ctx.Cookie("someKey") // $ Source[go/reflected-xss] val, _ := ctx.Cookie("someKey")
ctx.HTML(200, val.Value) // $ Alert[go/reflected-xss] ctx.HTML(200, val.Value)
return nil return nil
} }
func testCookies(ctx echo.Context) error { func testCookies(ctx echo.Context) error {
cookies := ctx.Cookies() // $ Source[go/reflected-xss] cookies := ctx.Cookies()
ctx.HTML(200, cookies[0].Value) // $ Alert[go/reflected-xss] ctx.HTML(200, cookies[0].Value)
return nil return nil
} }
@@ -96,8 +96,8 @@ type myStruct struct {
func testBind(ctx echo.Context) error { func testBind(ctx echo.Context) error {
data := myStruct{} data := myStruct{}
ctx.Bind(&data) // $ Source[go/reflected-xss] ctx.Bind(&data)
ctx.HTML(200, data.s) // $ Alert[go/reflected-xss] ctx.HTML(200, data.s)
return nil return nil
} }
@@ -110,8 +110,8 @@ func testGetSetEmpty(ctx echo.Context) error {
} }
func testGetSet(ctx echo.Context) error { func testGetSet(ctx echo.Context) error {
ctx.Set("someKey", ctx.Param("someParam")) // $ Source[go/reflected-xss] ctx.Set("someKey", ctx.Param("someParam"))
ctx.HTML(200, ctx.Get("someKey").(string)) // $ Alert[go/reflected-xss] // BAD, the context is tainted ctx.HTML(200, ctx.Get("someKey").(string)) // BAD, the context is tainted
return nil return nil
} }
@@ -121,20 +121,20 @@ func testGetSet(ctx echo.Context) error {
// All are XSS vulnerabilities, except as specifically noted. // All are XSS vulnerabilities, except as specifically noted.
func testHTML(ctx echo.Context) error { func testHTML(ctx echo.Context) error {
param := ctx.Param("someParam") // $ Source[go/reflected-xss] param := ctx.Param("someParam")
ctx.HTML(200, param) // $ Alert[go/reflected-xss] ctx.HTML(200, param)
return nil return nil
} }
func testHTMLBlob(ctx echo.Context) error { func testHTMLBlob(ctx echo.Context) error {
param := ctx.Param("someParam") // $ Source[go/reflected-xss] param := ctx.Param("someParam")
ctx.HTMLBlob(200, []byte(param)) // $ Alert[go/reflected-xss] ctx.HTMLBlob(200, []byte(param))
return nil return nil
} }
func testBlob(ctx echo.Context) error { func testBlob(ctx echo.Context) error {
param := ctx.Param("someParam") // $ Source[go/reflected-xss] param := ctx.Param("someParam")
ctx.Blob(200, "text/html", []byte(param)) // $ Alert[go/reflected-xss] // BAD, the content-type is HTML ctx.Blob(200, "text/html", []byte(param)) // BAD, the content-type is HTML
return nil return nil
} }
@@ -145,9 +145,9 @@ func testBlobSafe(ctx echo.Context) error {
} }
func testStream(ctx echo.Context) error { func testStream(ctx echo.Context) error {
param := ctx.Param("someParam") // $ Source[go/reflected-xss] param := ctx.Param("someParam")
reader := strings.NewReader(param) reader := strings.NewReader(param)
ctx.Stream(200, "text/html", reader) // $ Alert[go/reflected-xss] // BAD, the content-type is HTML ctx.Stream(200, "text/html", reader) // BAD, the content-type is HTML
return nil return nil
} }
@@ -161,28 +161,28 @@ func testStreamSafe(ctx echo.Context) error {
// Section: testing output methods defined on Response (XSS vulnerability) // Section: testing output methods defined on Response (XSS vulnerability)
func testResponseWrite(ctx echo.Context) error { func testResponseWrite(ctx echo.Context) error {
param := ctx.Param("someParam") // $ Source[go/reflected-xss] param := ctx.Param("someParam")
ctx.Response().Write([]byte(param)) // $ Alert[go/reflected-xss] ctx.Response().Write([]byte(param))
return nil return nil
} }
// Section: test detecting an open redirect using the Context.Redirect function: // Section: test detecting an open redirect using the Context.Redirect function:
func testRedirect(ctx echo.Context) error { func testRedirect(ctx echo.Context) error {
param := ctx.Param("someParam") // $ Source[go/unvalidated-url-redirection] param := ctx.Param("someParam")
ctx.Redirect(301, param) // $ Alert[go/unvalidated-url-redirection] ctx.Redirect(301, param)
return nil return nil
} }
func testLocalRedirects(ctx echo.Context) error { func testLocalRedirects(ctx echo.Context) error {
param := ctx.Param("someParam") // $ Source[go/unvalidated-url-redirection] param := ctx.Param("someParam")
param2 := param param2 := param
param3 := param param3 := param
// Gratuitous copy because sanitization of uses propagates to subsequent uses // Gratuitous copy because sanitization of uses propagates to subsequent uses
// GOOD: local redirects are unproblematic // GOOD: local redirects are unproblematic
ctx.Redirect(301, "/local"+param) ctx.Redirect(301, "/local"+param)
// BAD: this could be a non-local redirect // BAD: this could be a non-local redirect
ctx.Redirect(301, "/"+param2) // $ Alert[go/unvalidated-url-redirection] ctx.Redirect(301, "/"+param2)
// GOOD: localhost redirects are unproblematic // GOOD: localhost redirects are unproblematic
ctx.Redirect(301, "//localhost/"+param3) ctx.Redirect(301, "//localhost/"+param3)
return nil return nil
@@ -221,12 +221,12 @@ func testNonExploitableFields(ctx echo.Context) error {
func fsOpsTest() { func fsOpsTest() {
e := echo.New() e := echo.New()
e.GET("/", func(c echo.Context) error { e.GET("/", func(c echo.Context) error {
filepath := c.QueryParam("filePath") // $ Source[go/path-injection] filepath := c.QueryParam("filePath")
return c.File(filepath) // $ FileSystemAccess=filepath Alert[go/path-injection] return c.File(filepath) // $ FileSystemAccess=filepath
}) })
e.GET("/attachment", func(c echo.Context) error { e.GET("/attachment", func(c echo.Context) error {
filepath := c.QueryParam("filePath") // $ Source[go/path-injection] filepath := c.QueryParam("filePath")
return c.Attachment(filepath, "file name in response") // $ FileSystemAccess=filepath Alert[go/path-injection] return c.Attachment(filepath, "file name in response") // $ FileSystemAccess=filepath
}) })
_ = e.Start(":1323") _ = e.Start(":1323")
} }

View File

@@ -1,8 +1,8 @@
#select
| main.go:21:28:21:31 | name | main.go:18:46:18:48 | definition of req | main.go:21:28:21:31 | name | This log entry depends on a $@. | main.go:18:46:18:48 | definition of req | user-provided value |
edges edges
| main.go:18:46:18:48 | definition of req | main.go:21:28:21:31 | name | provenance | | | main.go:18:46:18:48 | definition of req | main.go:21:28:21:31 | name | provenance | |
nodes nodes
| main.go:18:46:18:48 | definition of req | semmle.label | definition of req | | main.go:18:46:18:48 | definition of req | semmle.label | definition of req |
| main.go:21:28:21:31 | name | semmle.label | name | | main.go:21:28:21:31 | name | semmle.label | name |
subpaths subpaths
#select
| main.go:21:28:21:31 | name | main.go:18:46:18:48 | definition of req | main.go:21:28:21:31 | name | This log entry depends on a $@. | main.go:18:46:18:48 | definition of req | user-provided value |

View File

@@ -1,2 +1 @@
query: Security/CWE-117/LogInjection.ql Security/CWE-117/LogInjection.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -15,10 +15,10 @@ import (
type Greeter struct{} type Greeter struct{}
func (g *Greeter) Hello(ctx context.Context, req *pb.Request, rsp *pb.Response) error { // $ serverRequest="definition of req" Source func (g *Greeter) Hello(ctx context.Context, req *pb.Request, rsp *pb.Response) error { // $ serverRequest="definition of req"
// var access // var access
name := req.Name name := req.Name
fmt.Println("Name :: %s", name) // $ Alert fmt.Println("Name :: %s", name)
return nil return nil
} }

View File

@@ -1,28 +1,28 @@
reverseRead reverseRead
| EndToEnd.go:31:35:31:35 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | | EndToEnd.go:30:35:30:35 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
| EndToEnd.go:31:35:31:42 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | | EndToEnd.go:30:35:30:42 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
| EndToEnd.go:37:18:37:18 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | | EndToEnd.go:36:18:36:18 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
| EndToEnd.go:37:18:37:25 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | | EndToEnd.go:36:18:36:25 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
| EndToEnd.go:45:18:45:18 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | | EndToEnd.go:44:18:44:18 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
| EndToEnd.go:45:18:45:25 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | | EndToEnd.go:44:18:44:25 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
| EndToEnd.go:52:20:52:20 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | | EndToEnd.go:51:20:51:20 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
| EndToEnd.go:52:20:52:27 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | | EndToEnd.go:51:20:51:27 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
| EndToEnd.go:59:18:59:18 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | | EndToEnd.go:58:18:58:18 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
| EndToEnd.go:59:18:59:25 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | | EndToEnd.go:58:18:58:25 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
| EndToEnd.go:65:26:65:26 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | | EndToEnd.go:64:26:64:26 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
| EndToEnd.go:65:26:65:33 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | | EndToEnd.go:64:26:64:33 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
| EndToEnd.go:70:22:70:22 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | | EndToEnd.go:69:22:69:22 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
| EndToEnd.go:70:22:70:29 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | | EndToEnd.go:69:22:69:29 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
| EndToEnd.go:75:22:75:22 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | | EndToEnd.go:74:22:74:22 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
| EndToEnd.go:75:22:75:29 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | | EndToEnd.go:74:22:74:29 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
| EndToEnd.go:80:35:80:35 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | | EndToEnd.go:79:35:79:35 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
| EndToEnd.go:80:35:80:42 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | | EndToEnd.go:79:35:79:42 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
| EndToEnd.go:85:22:85:22 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | | EndToEnd.go:84:22:84:22 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
| EndToEnd.go:85:22:85:29 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | | EndToEnd.go:84:22:84:29 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
| EndToEnd.go:90:21:90:21 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | | EndToEnd.go:89:21:89:21 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
| EndToEnd.go:90:21:90:28 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | | EndToEnd.go:89:21:89:28 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
| EndToEnd.go:95:20:95:20 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | | EndToEnd.go:94:20:94:20 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
| EndToEnd.go:95:20:95:27 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | | EndToEnd.go:94:20:94:27 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |
| Revel.go:26:7:26:7 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | | Revel.go:26:7:26:7 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
| Revel.go:27:7:27:7 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. | | Revel.go:27:7:27:7 | implicit read of field Controller | Origin of readStep is missing a PostUpdateNode. |
| Revel.go:27:7:27:14 | implicit dereference | Origin of readStep is missing a PostUpdateNode. | | Revel.go:27:7:27:14 | implicit dereference | Origin of readStep is missing a PostUpdateNode. |

View File

@@ -3,11 +3,10 @@ package main
import ( import (
"bytes" "bytes"
"errors" "errors"
"os"
"time"
staticControllers "github.com/revel/modules/static/app/controllers" staticControllers "github.com/revel/modules/static/app/controllers"
"github.com/revel/revel" "github.com/revel/revel"
"os"
"time"
) )
// Use typical inheritence pattern, per github.com/revel/examples/booking: // Use typical inheritence pattern, per github.com/revel/examples/booking:
@@ -34,8 +33,8 @@ func (c MyRoute) Handler1() revel.Result {
func (c MyRoute) Handler2() revel.Result { func (c MyRoute) Handler2() revel.Result {
// BAD: the RenderBinary function copies an `io.Reader` to the user's browser. // BAD: the RenderBinary function copies an `io.Reader` to the user's browser.
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
buf.WriteString(c.Params.Form.Get("someField")) // $ Source[go/reflected-xss] buf.WriteString(c.Params.Form.Get("someField"))
return c.RenderBinary(buf, "index.html", revel.Inline, time.Now()) // $ responsebody='buf' Alert[go/reflected-xss] return c.RenderBinary(buf, "index.html", revel.Inline, time.Now()) // $ responsebody='buf'
} }
func (c MyRoute) Handler3() revel.Result { func (c MyRoute) Handler3() revel.Result {
@@ -56,18 +55,18 @@ func (c MyRoute) Handler4() revel.Result {
func (c MyRoute) Handler5() revel.Result { func (c MyRoute) Handler5() revel.Result {
// BAD: returning an arbitrary file (but this is detected at the os.Open call, not // BAD: returning an arbitrary file (but this is detected at the os.Open call, not
// due to modelling Revel) // due to modelling Revel)
f, _ := os.Open(c.Params.Form.Get("someField")) // $ Alert[go/path-injection] f, _ := os.Open(c.Params.Form.Get("someField"))
return c.RenderFile(f, revel.Inline) return c.RenderFile(f, revel.Inline)
} }
func (c MyRoute) Handler6() revel.Result { func (c MyRoute) Handler6() revel.Result {
// BAD: returning an arbitrary file (detected as a user-controlled file-op, not XSS) // BAD: returning an arbitrary file (detected as a user-controlled file-op, not XSS)
return c.RenderFileName(c.Params.Form.Get("someField"), revel.Inline) // $ Alert[go/path-injection] return c.RenderFileName(c.Params.Form.Get("someField"), revel.Inline)
} }
func (c MyRoute) Handler7() revel.Result { func (c MyRoute) Handler7() revel.Result {
// BAD: straightforward XSS // BAD: straightforward XSS
return c.RenderHTML(c.Params.Form.Get("someField")) // $ responsebody='call to Get' Alert[go/reflected-xss] return c.RenderHTML(c.Params.Form.Get("someField")) // $ responsebody='call to Get'
} }
func (c MyRoute) Handler8() revel.Result { func (c MyRoute) Handler8() revel.Result {
@@ -92,5 +91,5 @@ func (c MyRoute) Handler11() revel.Result {
func (c MyRoute) Handler12() revel.Result { func (c MyRoute) Handler12() revel.Result {
// BAD: open redirect // BAD: open redirect
return c.Redirect(c.Params.Form.Get("someField")) // $ Alert[go/unvalidated-url-redirection] return c.Redirect(c.Params.Form.Get("someField"))
} }

View File

@@ -1,19 +1,19 @@
#select #select
| EndToEnd.go:95:20:95:49 | call to Get | EndToEnd.go:95:20:95:27 | selection of Params | EndToEnd.go:95:20:95:49 | call to Get | This path to an untrusted URL redirection depends on a $@. | EndToEnd.go:95:20:95:27 | selection of Params | user-provided value | | EndToEnd.go:94:20:94:49 | call to Get | EndToEnd.go:94:20:94:27 | selection of Params | EndToEnd.go:94:20:94:49 | call to Get | This path to an untrusted URL redirection depends on a $@. | EndToEnd.go:94:20:94:27 | selection of Params | user-provided value |
edges edges
| EndToEnd.go:95:20:95:27 | implicit dereference | EndToEnd.go:95:20:95:27 | selection of Params [postupdate] | provenance | Config | | EndToEnd.go:94:20:94:27 | implicit dereference | EndToEnd.go:94:20:94:27 | selection of Params [postupdate] | provenance | Config |
| EndToEnd.go:95:20:95:27 | implicit dereference | EndToEnd.go:95:20:95:32 | selection of Form | provenance | Config | | EndToEnd.go:94:20:94:27 | implicit dereference | EndToEnd.go:94:20:94:32 | selection of Form | provenance | Config |
| EndToEnd.go:95:20:95:27 | selection of Params | EndToEnd.go:95:20:95:27 | implicit dereference | provenance | Src:MaD:2 Config | | EndToEnd.go:94:20:94:27 | selection of Params | EndToEnd.go:94:20:94:27 | implicit dereference | provenance | Src:MaD:2 Config |
| EndToEnd.go:95:20:95:27 | selection of Params | EndToEnd.go:95:20:95:32 | selection of Form | provenance | Src:MaD:2 Config | | EndToEnd.go:94:20:94:27 | selection of Params | EndToEnd.go:94:20:94:32 | selection of Form | provenance | Src:MaD:2 Config |
| EndToEnd.go:95:20:95:27 | selection of Params [postupdate] | EndToEnd.go:95:20:95:27 | implicit dereference | provenance | Config | | EndToEnd.go:94:20:94:27 | selection of Params [postupdate] | EndToEnd.go:94:20:94:27 | implicit dereference | provenance | Config |
| EndToEnd.go:95:20:95:32 | selection of Form | EndToEnd.go:95:20:95:49 | call to Get | provenance | Config Sink:MaD:1 | | EndToEnd.go:94:20:94:32 | selection of Form | EndToEnd.go:94:20:94:49 | call to Get | provenance | Config Sink:MaD:1 |
models models
| 1 | Sink: group:revel; Controller; true; Redirect; ; ; Argument[0]; url-redirection; manual | | 1 | Sink: group:revel; Controller; true; Redirect; ; ; Argument[0]; url-redirection; manual |
| 2 | Source: group:revel; Controller; true; Params; ; ; ; remote; manual | | 2 | Source: group:revel; Controller; true; Params; ; ; ; remote; manual |
nodes nodes
| EndToEnd.go:95:20:95:27 | implicit dereference | semmle.label | implicit dereference | | EndToEnd.go:94:20:94:27 | implicit dereference | semmle.label | implicit dereference |
| EndToEnd.go:95:20:95:27 | selection of Params | semmle.label | selection of Params | | EndToEnd.go:94:20:94:27 | selection of Params | semmle.label | selection of Params |
| EndToEnd.go:95:20:95:27 | selection of Params [postupdate] | semmle.label | selection of Params [postupdate] | | EndToEnd.go:94:20:94:27 | selection of Params [postupdate] | semmle.label | selection of Params [postupdate] |
| EndToEnd.go:95:20:95:32 | selection of Form | semmle.label | selection of Form | | EndToEnd.go:94:20:94:32 | selection of Form | semmle.label | selection of Form |
| EndToEnd.go:95:20:95:49 | call to Get | semmle.label | call to Get | | EndToEnd.go:94:20:94:49 | call to Get | semmle.label | call to Get |
subpaths subpaths

View File

@@ -1,4 +1,2 @@
query: Security/CWE-601/OpenUrlRedirect.ql query: Security/CWE-601/OpenUrlRedirect.ql
postprocess: postprocess: utils/test/PrettyPrintModels.ql
- utils/test/PrettyPrintModels.ql
- utils/test/InlineExpectationsTestQuery.ql

View File

@@ -1,16 +1,16 @@
#select #select
| EndToEnd.go:38:24:38:26 | buf | EndToEnd.go:37:18:37:25 | selection of Params | EndToEnd.go:38:24:38:26 | buf | Cross-site scripting vulnerability due to $@. | EndToEnd.go:37:18:37:25 | selection of Params | user-provided value | EndToEnd.go:0:0:0:0 | EndToEnd.go | | | EndToEnd.go:37:24:37:26 | buf | EndToEnd.go:36:18:36:25 | selection of Params | EndToEnd.go:37:24:37:26 | buf | Cross-site scripting vulnerability due to $@. | EndToEnd.go:36:18:36:25 | selection of Params | user-provided value | EndToEnd.go:0:0:0:0 | EndToEnd.go | |
| EndToEnd.go:70:22:70:51 | call to Get | EndToEnd.go:70:22:70:29 | selection of Params | EndToEnd.go:70:22:70:51 | call to Get | Cross-site scripting vulnerability due to $@. | EndToEnd.go:70:22:70:29 | selection of Params | user-provided value | EndToEnd.go:0:0:0:0 | EndToEnd.go | | | EndToEnd.go:69:22:69:51 | call to Get | EndToEnd.go:69:22:69:29 | selection of Params | EndToEnd.go:69:22:69:51 | call to Get | Cross-site scripting vulnerability due to $@. | EndToEnd.go:69:22:69:29 | selection of Params | user-provided value | EndToEnd.go:0:0:0:0 | EndToEnd.go | |
| Revel.go:70:22:70:35 | selection of Query | Revel.go:70:22:70:29 | selection of Params | Revel.go:70:22:70:35 | selection of Query | Cross-site scripting vulnerability due to $@. The value is $@. | Revel.go:70:22:70:29 | selection of Params | user-provided value | views/myAppController/rawRead.html:1:1:2:9 | {{raw .Foo}}\n{{.Bar}}\n | instantiated as a raw template | | Revel.go:70:22:70:35 | selection of Query | Revel.go:70:22:70:29 | selection of Params | Revel.go:70:22:70:35 | selection of Query | Cross-site scripting vulnerability due to $@. The value is $@. | Revel.go:70:22:70:29 | selection of Params | user-provided value | views/myAppController/rawRead.html:1:1:2:9 | {{raw .Foo}}\n{{.Bar}}\n | instantiated as a raw template |
| examples/booking/app/init.go:36:44:36:53 | selection of Path | examples/booking/app/init.go:36:44:36:48 | selection of URL | examples/booking/app/init.go:36:44:36:53 | selection of Path | Cross-site scripting vulnerability due to $@. | examples/booking/app/init.go:36:44:36:48 | selection of URL | user-provided value | examples/booking/app/init.go:0:0:0:0 | examples/booking/app/init.go | | | examples/booking/app/init.go:36:44:36:53 | selection of Path | examples/booking/app/init.go:36:44:36:48 | selection of URL | examples/booking/app/init.go:36:44:36:53 | selection of Path | Cross-site scripting vulnerability due to $@. | examples/booking/app/init.go:36:44:36:48 | selection of URL | user-provided value | examples/booking/app/init.go:0:0:0:0 | examples/booking/app/init.go | |
| examples/booking/app/init.go:40:49:40:58 | selection of Path | examples/booking/app/init.go:40:49:40:53 | selection of URL | examples/booking/app/init.go:40:49:40:58 | selection of Path | Cross-site scripting vulnerability due to $@. | examples/booking/app/init.go:40:49:40:53 | selection of URL | user-provided value | examples/booking/app/init.go:0:0:0:0 | examples/booking/app/init.go | | | examples/booking/app/init.go:40:49:40:58 | selection of Path | examples/booking/app/init.go:40:49:40:53 | selection of URL | examples/booking/app/init.go:40:49:40:58 | selection of Path | Cross-site scripting vulnerability due to $@. | examples/booking/app/init.go:40:49:40:53 | selection of URL | user-provided value | examples/booking/app/init.go:0:0:0:0 | examples/booking/app/init.go | |
edges edges
| EndToEnd.go:37:2:37:4 | buf [postupdate] | EndToEnd.go:38:24:38:26 | buf | provenance | | | EndToEnd.go:36:2:36:4 | buf [postupdate] | EndToEnd.go:37:24:37:26 | buf | provenance | |
| EndToEnd.go:37:18:37:25 | selection of Params | EndToEnd.go:37:18:37:30 | selection of Form | provenance | Src:MaD:1 | | EndToEnd.go:36:18:36:25 | selection of Params | EndToEnd.go:36:18:36:30 | selection of Form | provenance | Src:MaD:1 |
| EndToEnd.go:37:18:37:30 | selection of Form | EndToEnd.go:37:18:37:47 | call to Get | provenance | MaD:4 | | EndToEnd.go:36:18:36:30 | selection of Form | EndToEnd.go:36:18:36:47 | call to Get | provenance | MaD:4 |
| EndToEnd.go:37:18:37:47 | call to Get | EndToEnd.go:37:2:37:4 | buf [postupdate] | provenance | MaD:3 | | EndToEnd.go:36:18:36:47 | call to Get | EndToEnd.go:36:2:36:4 | buf [postupdate] | provenance | MaD:3 |
| EndToEnd.go:70:22:70:29 | selection of Params | EndToEnd.go:70:22:70:34 | selection of Form | provenance | Src:MaD:1 | | EndToEnd.go:69:22:69:29 | selection of Params | EndToEnd.go:69:22:69:34 | selection of Form | provenance | Src:MaD:1 |
| EndToEnd.go:70:22:70:34 | selection of Form | EndToEnd.go:70:22:70:51 | call to Get | provenance | MaD:4 | | EndToEnd.go:69:22:69:34 | selection of Form | EndToEnd.go:69:22:69:51 | call to Get | provenance | MaD:4 |
| Revel.go:70:22:70:29 | selection of Params | Revel.go:70:22:70:35 | selection of Query | provenance | Src:MaD:1 | | Revel.go:70:22:70:29 | selection of Params | Revel.go:70:22:70:35 | selection of Query | provenance | Src:MaD:1 |
| examples/booking/app/init.go:36:44:36:48 | selection of URL | examples/booking/app/init.go:36:44:36:53 | selection of Path | provenance | Src:MaD:2 | | examples/booking/app/init.go:36:44:36:48 | selection of URL | examples/booking/app/init.go:36:44:36:53 | selection of Path | provenance | Src:MaD:2 |
| examples/booking/app/init.go:40:49:40:53 | selection of URL | examples/booking/app/init.go:40:49:40:58 | selection of Path | provenance | Src:MaD:2 | | examples/booking/app/init.go:40:49:40:53 | selection of URL | examples/booking/app/init.go:40:49:40:58 | selection of Path | provenance | Src:MaD:2 |
@@ -20,14 +20,14 @@ models
| 3 | Summary: io; StringWriter; true; WriteString; ; ; Argument[0]; Argument[receiver]; taint; manual | | 3 | Summary: io; StringWriter; true; WriteString; ; ; Argument[0]; Argument[receiver]; taint; manual |
| 4 | Summary: net/url; Values; true; Get; ; ; Argument[receiver]; ReturnValue; taint; manual | | 4 | Summary: net/url; Values; true; Get; ; ; Argument[receiver]; ReturnValue; taint; manual |
nodes nodes
| EndToEnd.go:37:2:37:4 | buf [postupdate] | semmle.label | buf [postupdate] | | EndToEnd.go:36:2:36:4 | buf [postupdate] | semmle.label | buf [postupdate] |
| EndToEnd.go:37:18:37:25 | selection of Params | semmle.label | selection of Params | | EndToEnd.go:36:18:36:25 | selection of Params | semmle.label | selection of Params |
| EndToEnd.go:37:18:37:30 | selection of Form | semmle.label | selection of Form | | EndToEnd.go:36:18:36:30 | selection of Form | semmle.label | selection of Form |
| EndToEnd.go:37:18:37:47 | call to Get | semmle.label | call to Get | | EndToEnd.go:36:18:36:47 | call to Get | semmle.label | call to Get |
| EndToEnd.go:38:24:38:26 | buf | semmle.label | buf | | EndToEnd.go:37:24:37:26 | buf | semmle.label | buf |
| EndToEnd.go:70:22:70:29 | selection of Params | semmle.label | selection of Params | | EndToEnd.go:69:22:69:29 | selection of Params | semmle.label | selection of Params |
| EndToEnd.go:70:22:70:34 | selection of Form | semmle.label | selection of Form | | EndToEnd.go:69:22:69:34 | selection of Form | semmle.label | selection of Form |
| EndToEnd.go:70:22:70:51 | call to Get | semmle.label | call to Get | | EndToEnd.go:69:22:69:51 | call to Get | semmle.label | call to Get |
| Revel.go:70:22:70:29 | selection of Params | semmle.label | selection of Params | | Revel.go:70:22:70:29 | selection of Params | semmle.label | selection of Params |
| Revel.go:70:22:70:35 | selection of Query | semmle.label | selection of Query | | Revel.go:70:22:70:35 | selection of Query | semmle.label | selection of Query |
| examples/booking/app/init.go:36:44:36:48 | selection of URL | semmle.label | selection of URL | | examples/booking/app/init.go:36:44:36:48 | selection of URL | semmle.label | selection of URL |

View File

@@ -1,4 +1,2 @@
query: Security/CWE-079/ReflectedXss.ql query: Security/CWE-079/ReflectedXss.ql
postprocess: postprocess: utils/test/PrettyPrintModels.ql
- utils/test/PrettyPrintModels.ql
- utils/test/InlineExpectationsTestQuery.ql

View File

@@ -67,7 +67,7 @@ func (c myAppController) accessingParamsJSONIsUnsafe() {
func (c myAppController) rawRead() { // $ responsebody='argument corresponding to c' func (c myAppController) rawRead() { // $ responsebody='argument corresponding to c'
c.ViewArgs["Foo"] = "<p>raw HTML</p>" // $ responsebody='"<p>raw HTML</p>"' c.ViewArgs["Foo"] = "<p>raw HTML</p>" // $ responsebody='"<p>raw HTML</p>"'
c.ViewArgs["Bar"] = "<p>not raw HTML</p>" c.ViewArgs["Bar"] = "<p>not raw HTML</p>"
c.ViewArgs["Foo"] = c.Params.Query // $ responsebody='selection of Query' Alert[go/reflected-xss] c.ViewArgs["Foo"] = c.Params.Query // $ responsebody='selection of Query'
c.Render() c.Render()
} }

View File

@@ -1,21 +1,21 @@
#select #select
| EndToEnd.go:59:18:59:47 | call to Get | EndToEnd.go:59:18:59:25 | selection of Params | EndToEnd.go:59:18:59:47 | call to Get | This path depends on a $@. | EndToEnd.go:59:18:59:25 | selection of Params | user-provided value | | EndToEnd.go:58:18:58:47 | call to Get | EndToEnd.go:58:18:58:25 | selection of Params | EndToEnd.go:58:18:58:47 | call to Get | This path depends on a $@. | EndToEnd.go:58:18:58:25 | selection of Params | user-provided value |
| EndToEnd.go:65:26:65:55 | call to Get | EndToEnd.go:65:26:65:33 | selection of Params | EndToEnd.go:65:26:65:55 | call to Get | This path depends on a $@. | EndToEnd.go:65:26:65:33 | selection of Params | user-provided value | | EndToEnd.go:64:26:64:55 | call to Get | EndToEnd.go:64:26:64:33 | selection of Params | EndToEnd.go:64:26:64:55 | call to Get | This path depends on a $@. | EndToEnd.go:64:26:64:33 | selection of Params | user-provided value |
edges edges
| EndToEnd.go:59:18:59:25 | selection of Params | EndToEnd.go:59:18:59:30 | selection of Form | provenance | Src:MaD:3 | | EndToEnd.go:58:18:58:25 | selection of Params | EndToEnd.go:58:18:58:30 | selection of Form | provenance | Src:MaD:3 |
| EndToEnd.go:59:18:59:30 | selection of Form | EndToEnd.go:59:18:59:47 | call to Get | provenance | MaD:4 Sink:MaD:2 | | EndToEnd.go:58:18:58:30 | selection of Form | EndToEnd.go:58:18:58:47 | call to Get | provenance | MaD:4 Sink:MaD:2 |
| EndToEnd.go:65:26:65:33 | selection of Params | EndToEnd.go:65:26:65:38 | selection of Form | provenance | Src:MaD:3 | | EndToEnd.go:64:26:64:33 | selection of Params | EndToEnd.go:64:26:64:38 | selection of Form | provenance | Src:MaD:3 |
| EndToEnd.go:65:26:65:38 | selection of Form | EndToEnd.go:65:26:65:55 | call to Get | provenance | MaD:4 Sink:MaD:1 | | EndToEnd.go:64:26:64:38 | selection of Form | EndToEnd.go:64:26:64:55 | call to Get | provenance | MaD:4 Sink:MaD:1 |
models models
| 1 | Sink: group:revel; Controller; true; RenderFileName; ; ; Argument[0]; path-injection; manual | | 1 | Sink: group:revel; Controller; true; RenderFileName; ; ; Argument[0]; path-injection; manual |
| 2 | Sink: os; ; false; Open; ; ; Argument[0]; path-injection; manual | | 2 | Sink: os; ; false; Open; ; ; Argument[0]; path-injection; manual |
| 3 | Source: group:revel; Controller; true; Params; ; ; ; remote; manual | | 3 | Source: group:revel; Controller; true; Params; ; ; ; remote; manual |
| 4 | Summary: net/url; Values; true; Get; ; ; Argument[receiver]; ReturnValue; taint; manual | | 4 | Summary: net/url; Values; true; Get; ; ; Argument[receiver]; ReturnValue; taint; manual |
nodes nodes
| EndToEnd.go:59:18:59:25 | selection of Params | semmle.label | selection of Params | | EndToEnd.go:58:18:58:25 | selection of Params | semmle.label | selection of Params |
| EndToEnd.go:59:18:59:30 | selection of Form | semmle.label | selection of Form | | EndToEnd.go:58:18:58:30 | selection of Form | semmle.label | selection of Form |
| EndToEnd.go:59:18:59:47 | call to Get | semmle.label | call to Get | | EndToEnd.go:58:18:58:47 | call to Get | semmle.label | call to Get |
| EndToEnd.go:65:26:65:33 | selection of Params | semmle.label | selection of Params | | EndToEnd.go:64:26:64:33 | selection of Params | semmle.label | selection of Params |
| EndToEnd.go:65:26:65:38 | selection of Form | semmle.label | selection of Form | | EndToEnd.go:64:26:64:38 | selection of Form | semmle.label | selection of Form |
| EndToEnd.go:65:26:65:55 | call to Get | semmle.label | call to Get | | EndToEnd.go:64:26:64:55 | call to Get | semmle.label | call to Get |
subpaths subpaths

View File

@@ -1,4 +1,2 @@
query: Security/CWE-022/TaintedPath.ql query: Security/CWE-022/TaintedPath.ql
postprocess: postprocess: utils/test/PrettyPrintModels.ql
- utils/test/PrettyPrintModels.ql
- utils/test/InlineExpectationsTestQuery.ql

View File

@@ -33,11 +33,11 @@ func init() {
switch event { switch event {
case revel.ENGINE_BEFORE_INITIALIZED: case revel.ENGINE_BEFORE_INITIALIZED:
revel.AddHTTPMux("/this/is/a/test", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { revel.AddHTTPMux("/this/is/a/test", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hi there, it worked", r.URL.Path) // $ responsebody='selection of Path' responsebody='"Hi there, it worked"' Alert[go/reflected-xss] fmt.Fprintln(w, "Hi there, it worked", r.URL.Path) // $ responsebody='selection of Path' responsebody='"Hi there, it worked"'
w.WriteHeader(200) w.WriteHeader(200)
})) }))
revel.AddHTTPMux("/this/is/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { revel.AddHTTPMux("/this/is/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hi there, shorter prefix", r.URL.Path) // $ responsebody='selection of Path' responsebody='"Hi there, shorter prefix"' Alert[go/reflected-xss] fmt.Fprintln(w, "Hi there, shorter prefix", r.URL.Path) // $ responsebody='selection of Path' responsebody='"Hi there, shorter prefix"'
w.WriteHeader(200) w.WriteHeader(200)
})) }))
} }

View File

@@ -1,4 +1,2 @@
query: Security/CWE-918/RequestForgery.ql query: Security/CWE-918/RequestForgery.ql
postprocess: postprocess: utils/test/PrettyPrintModels.ql
- utils/test/PrettyPrintModels.ql
- utils/test/InlineExpectationsTestQuery.ql

View File

@@ -9,7 +9,7 @@ import (
) )
func main() { func main() {
client := notes.NewNotesServiceProtobufClient("http://localhost:8000", &http.Client{}) // $ ssrfSink client := notes.NewNotesServiceProtobufClient("http://localhost:8000", &http.Client{}) // test: ssrfSink
ctx := context.Background() ctx := context.Background()

View File

@@ -20,7 +20,7 @@ const (
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
) )
type Note struct { // $ message type Note struct { // test: message
state protoimpl.MessageState state protoimpl.MessageState
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
@@ -83,7 +83,7 @@ func (x *Note) GetCreatedAt() int64 {
return 0 return 0
} }
type CreateNoteParams struct { // $ message type CreateNoteParams struct { // test: message
state protoimpl.MessageState state protoimpl.MessageState
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
@@ -130,7 +130,7 @@ func (x *CreateNoteParams) GetText() string {
return "" return ""
} }
type GetAllNotesParams struct { // $ message type GetAllNotesParams struct { // test: message
state protoimpl.MessageState state protoimpl.MessageState
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
@@ -168,7 +168,7 @@ func (*GetAllNotesParams) Descriptor() ([]byte, []int) {
return file_rpc_notes_service_proto_rawDescGZIP(), []int{2} return file_rpc_notes_service_proto_rawDescGZIP(), []int{2}
} }
type GetAllNotesResult struct { // $ message type GetAllNotesResult struct { // test: message
state protoimpl.MessageState state protoimpl.MessageState
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
@@ -340,7 +340,7 @@ func file_rpc_notes_service_proto_init() {
} }
} }
} }
type x struct{} // $ SPURIOUS: message // not message type x struct{}
out := protoimpl.TypeBuilder{ out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{ File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(), GoPackagePath: reflect.TypeOf(x{}).PkgPath(),

View File

@@ -31,7 +31,7 @@ const _ = twirp.TwirpPackageMinVersion_8_1_0
// NotesService Interface // NotesService Interface
// ====================== // ======================
type NotesService interface { // $ serviceInterface type NotesService interface { // test: serviceInterface
CreateNote(context.Context, *CreateNoteParams) (*Note, error) CreateNote(context.Context, *CreateNoteParams) (*Note, error)
GetAllNotes(context.Context, *GetAllNotesParams) (*GetAllNotesResult, error) GetAllNotes(context.Context, *GetAllNotesParams) (*GetAllNotesResult, error)
@@ -41,7 +41,7 @@ type NotesService interface { // $ serviceInterface
// NotesService Protobuf Client // NotesService Protobuf Client
// ============================ // ============================
type notesServiceProtobufClient struct { // $ serviceClient type notesServiceProtobufClient struct { // test: serviceClient
client HTTPClient client HTTPClient
urls [2]string urls [2]string
interceptor twirp.Interceptor interceptor twirp.Interceptor
@@ -50,7 +50,7 @@ type notesServiceProtobufClient struct { // $ serviceClient
// NewNotesServiceProtobufClient creates a Protobuf client that implements the NotesService interface. // NewNotesServiceProtobufClient creates a Protobuf client that implements the NotesService interface.
// It communicates using Protobuf and can be configured with a custom HTTPClient. // It communicates using Protobuf and can be configured with a custom HTTPClient.
func NewNotesServiceProtobufClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) NotesService { // $ clientConstructor func NewNotesServiceProtobufClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) NotesService { // test: clientConstructor
if c, ok := client.(*http.Client); ok { if c, ok := client.(*http.Client); ok {
client = withoutRedirects(c) client = withoutRedirects(c)
} }
@@ -84,7 +84,7 @@ func NewNotesServiceProtobufClient(baseURL string, client HTTPClient, opts ...tw
} }
} }
func (c *notesServiceProtobufClient) CreateNote(ctx context.Context, in *CreateNoteParams) (*Note, error) { // not handler func (c *notesServiceProtobufClient) CreateNote(ctx context.Context, in *CreateNoteParams) (*Note, error) { // test: !handler
ctx = ctxsetters.WithPackageName(ctx, "gotwirprpcexample.rpc.notes") ctx = ctxsetters.WithPackageName(ctx, "gotwirprpcexample.rpc.notes")
ctx = ctxsetters.WithServiceName(ctx, "NotesService") ctx = ctxsetters.WithServiceName(ctx, "NotesService")
ctx = ctxsetters.WithMethodName(ctx, "CreateNote") ctx = ctxsetters.WithMethodName(ctx, "CreateNote")
@@ -113,7 +113,7 @@ func (c *notesServiceProtobufClient) CreateNote(ctx context.Context, in *CreateN
return caller(ctx, in) return caller(ctx, in)
} }
func (c *notesServiceProtobufClient) callCreateNote(ctx context.Context, in *CreateNoteParams) (*Note, error) { // not handler func (c *notesServiceProtobufClient) callCreateNote(ctx context.Context, in *CreateNoteParams) (*Note, error) { // test: !handler
out := new(Note) out := new(Note)
ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[0], in, out) ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[0], in, out)
if err != nil { if err != nil {
@@ -130,7 +130,7 @@ func (c *notesServiceProtobufClient) callCreateNote(ctx context.Context, in *Cre
return out, nil return out, nil
} }
func (c *notesServiceProtobufClient) GetAllNotes(ctx context.Context, in *GetAllNotesParams) (*GetAllNotesResult, error) { // not handler func (c *notesServiceProtobufClient) GetAllNotes(ctx context.Context, in *GetAllNotesParams) (*GetAllNotesResult, error) { // test: !handler
ctx = ctxsetters.WithPackageName(ctx, "gotwirprpcexample.rpc.notes") ctx = ctxsetters.WithPackageName(ctx, "gotwirprpcexample.rpc.notes")
ctx = ctxsetters.WithServiceName(ctx, "NotesService") ctx = ctxsetters.WithServiceName(ctx, "NotesService")
ctx = ctxsetters.WithMethodName(ctx, "GetAllNotes") ctx = ctxsetters.WithMethodName(ctx, "GetAllNotes")
@@ -159,7 +159,7 @@ func (c *notesServiceProtobufClient) GetAllNotes(ctx context.Context, in *GetAll
return caller(ctx, in) return caller(ctx, in)
} }
func (c *notesServiceProtobufClient) callGetAllNotes(ctx context.Context, in *GetAllNotesParams) (*GetAllNotesResult, error) { // not handler func (c *notesServiceProtobufClient) callGetAllNotes(ctx context.Context, in *GetAllNotesParams) (*GetAllNotesResult, error) { // test: !handler
out := new(GetAllNotesResult) out := new(GetAllNotesResult)
ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[1], in, out) ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[1], in, out)
if err != nil { if err != nil {
@@ -180,7 +180,7 @@ func (c *notesServiceProtobufClient) callGetAllNotes(ctx context.Context, in *Ge
// NotesService JSON Client // NotesService JSON Client
// ======================== // ========================
type notesServiceJSONClient struct { // $ serviceClient type notesServiceJSONClient struct { // test: serviceClient
client HTTPClient client HTTPClient
urls [2]string urls [2]string
interceptor twirp.Interceptor interceptor twirp.Interceptor
@@ -189,7 +189,7 @@ type notesServiceJSONClient struct { // $ serviceClient
// NewNotesServiceJSONClient creates a JSON client that implements the NotesService interface. // NewNotesServiceJSONClient creates a JSON client that implements the NotesService interface.
// It communicates using JSON and can be configured with a custom HTTPClient. // It communicates using JSON and can be configured with a custom HTTPClient.
func NewNotesServiceJSONClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) NotesService { // $ clientConstructor func NewNotesServiceJSONClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) NotesService { // test: clientConstructor
if c, ok := client.(*http.Client); ok { if c, ok := client.(*http.Client); ok {
client = withoutRedirects(c) client = withoutRedirects(c)
} }
@@ -223,7 +223,7 @@ func NewNotesServiceJSONClient(baseURL string, client HTTPClient, opts ...twirp.
} }
} }
func (c *notesServiceJSONClient) CreateNote(ctx context.Context, in *CreateNoteParams) (*Note, error) { // not handler func (c *notesServiceJSONClient) CreateNote(ctx context.Context, in *CreateNoteParams) (*Note, error) { // test: !handler
ctx = ctxsetters.WithPackageName(ctx, "gotwirprpcexample.rpc.notes") ctx = ctxsetters.WithPackageName(ctx, "gotwirprpcexample.rpc.notes")
ctx = ctxsetters.WithServiceName(ctx, "NotesService") ctx = ctxsetters.WithServiceName(ctx, "NotesService")
ctx = ctxsetters.WithMethodName(ctx, "CreateNote") ctx = ctxsetters.WithMethodName(ctx, "CreateNote")
@@ -252,7 +252,7 @@ func (c *notesServiceJSONClient) CreateNote(ctx context.Context, in *CreateNoteP
return caller(ctx, in) return caller(ctx, in)
} }
func (c *notesServiceJSONClient) callCreateNote(ctx context.Context, in *CreateNoteParams) (*Note, error) { // not handler func (c *notesServiceJSONClient) callCreateNote(ctx context.Context, in *CreateNoteParams) (*Note, error) { // test: !handler
out := new(Note) out := new(Note)
ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[0], in, out) ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[0], in, out)
if err != nil { if err != nil {
@@ -269,7 +269,7 @@ func (c *notesServiceJSONClient) callCreateNote(ctx context.Context, in *CreateN
return out, nil return out, nil
} }
func (c *notesServiceJSONClient) GetAllNotes(ctx context.Context, in *GetAllNotesParams) (*GetAllNotesResult, error) { // not handler func (c *notesServiceJSONClient) GetAllNotes(ctx context.Context, in *GetAllNotesParams) (*GetAllNotesResult, error) { // test: !handler
ctx = ctxsetters.WithPackageName(ctx, "gotwirprpcexample.rpc.notes") ctx = ctxsetters.WithPackageName(ctx, "gotwirprpcexample.rpc.notes")
ctx = ctxsetters.WithServiceName(ctx, "NotesService") ctx = ctxsetters.WithServiceName(ctx, "NotesService")
ctx = ctxsetters.WithMethodName(ctx, "GetAllNotes") ctx = ctxsetters.WithMethodName(ctx, "GetAllNotes")
@@ -298,7 +298,7 @@ func (c *notesServiceJSONClient) GetAllNotes(ctx context.Context, in *GetAllNote
return caller(ctx, in) return caller(ctx, in)
} }
func (c *notesServiceJSONClient) callGetAllNotes(ctx context.Context, in *GetAllNotesParams) (*GetAllNotesResult, error) { // not handler func (c *notesServiceJSONClient) callGetAllNotes(ctx context.Context, in *GetAllNotesParams) (*GetAllNotesResult, error) { // test: !handler
out := new(GetAllNotesResult) out := new(GetAllNotesResult)
ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[1], in, out) ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[1], in, out)
if err != nil { if err != nil {
@@ -319,7 +319,7 @@ func (c *notesServiceJSONClient) callGetAllNotes(ctx context.Context, in *GetAll
// NotesService Server Handler // NotesService Server Handler
// =========================== // ===========================
type notesServiceServer struct { // $ serviceServer type notesServiceServer struct { // test: serviceServer
NotesService NotesService
interceptor twirp.Interceptor interceptor twirp.Interceptor
hooks *twirp.ServerHooks hooks *twirp.ServerHooks
@@ -331,7 +331,7 @@ type notesServiceServer struct { // $ serviceServer
// NewNotesServiceServer builds a TwirpServer that can be used as an http.Handler to handle // NewNotesServiceServer builds a TwirpServer that can be used as an http.Handler to handle
// HTTP requests that are routed to the right method in the provided svc implementation. // HTTP requests that are routed to the right method in the provided svc implementation.
// The opts are twirp.ServerOption modifiers, for example twirp.WithServerHooks(hooks). // The opts are twirp.ServerOption modifiers, for example twirp.WithServerHooks(hooks).
func NewNotesServiceServer(svc NotesService, opts ...interface{}) TwirpServer { // $ serverConstructor func NewNotesServiceServer(svc NotesService, opts ...interface{}) TwirpServer { // test: serverConstructor
serverOpts := newServerOpts(opts) serverOpts := newServerOpts(opts)
// Using ReadOpt allows backwards and forwards compatibility with new options in the future // Using ReadOpt allows backwards and forwards compatibility with new options in the future
@@ -535,7 +535,7 @@ func (s *notesServiceServer) serveCreateNoteProtobuf(ctx context.Context, resp h
return return
} }
buf, err := io.ReadAll(req.Body) // $ Source buf, err := io.ReadAll(req.Body)
if err != nil { if err != nil {
s.handleRequestBodyError(ctx, resp, "failed to read request body", err) s.handleRequestBodyError(ctx, resp, "failed to read request body", err)
return return
@@ -812,7 +812,7 @@ func (s *notesServiceServer) PathPrefix() string {
// automatically disabled if *(net/http).Client is passed to client // automatically disabled if *(net/http).Client is passed to client
// constructors. See the withoutRedirects function in this file for more // constructors. See the withoutRedirects function in this file for more
// details. // details.
type HTTPClient interface { // $ SPURIOUS: serviceInterface // not serviceInterface type HTTPClient interface {
Do(req *http.Request) (*http.Response, error) Do(req *http.Request) (*http.Response, error)
} }
@@ -820,7 +820,7 @@ type HTTPClient interface { // $ SPURIOUS: serviceInterface // not serviceInterf
// HTTP handlers with additional methods for accessing metadata about the // HTTP handlers with additional methods for accessing metadata about the
// service. Those accessors are a low-level API for building reflection tools. // service. Those accessors are a low-level API for building reflection tools.
// Most people can think of TwirpServers as just http.Handlers. // Most people can think of TwirpServers as just http.Handlers.
type TwirpServer interface { // $ SPURIOUS: serviceInterface // not serviceInterface type TwirpServer interface {
http.Handler http.Handler
// ServiceDescriptor returns gzipped bytes describing the .proto file that // ServiceDescriptor returns gzipped bytes describing the .proto file that

View File

@@ -16,7 +16,7 @@ type notesService struct {
CurrentId int32 CurrentId int32
} }
func (s *notesService) CreateNote(ctx context.Context, params *notes.CreateNoteParams) (*notes.Note, error) { // $ Source request handler // route handler func (s *notesService) CreateNote(ctx context.Context, params *notes.CreateNoteParams) (*notes.Note, error) { // test: routeHandler, request
if len(params.Text) < 4 { if len(params.Text) < 4 {
return nil, twirp.InvalidArgument.Error("Text should be min 4 characters.") return nil, twirp.InvalidArgument.Error("Text should be min 4 characters.")
} }
@@ -27,8 +27,8 @@ func (s *notesService) CreateNote(ctx context.Context, params *notes.CreateNoteP
CreatedAt: time.Now().UnixMilli(), CreatedAt: time.Now().UnixMilli(),
} }
notes.NewNotesServiceProtobufClient(params.Text, &http.Client{}) // $ Alert ssrfSink ssrf notes.NewNotesServiceProtobufClient(params.Text, &http.Client{}) // test: ssrfSink, ssrf
notes.NewNotesServiceProtobufClient(strconv.FormatInt(int64(s.CurrentId), 10), &http.Client{}) // $ ssrfSink // not ssrf notes.NewNotesServiceProtobufClient(strconv.FormatInt(int64(s.CurrentId), 10), &http.Client{}) // test: ssrfSink, !ssrf
s.Notes = append(s.Notes, note) s.Notes = append(s.Notes, note)
@@ -37,7 +37,7 @@ func (s *notesService) CreateNote(ctx context.Context, params *notes.CreateNoteP
return &note, nil return &note, nil
} }
func (s *notesService) GetAllNotes(ctx context.Context, params *notes.GetAllNotesParams) (*notes.GetAllNotesResult, error) { // $ request handler // route handler func (s *notesService) GetAllNotes(ctx context.Context, params *notes.GetAllNotesParams) (*notes.GetAllNotesResult, error) { // test: routeHandler, request
allNotes := make([]*notes.Note, 0) allNotes := make([]*notes.Note, 0)
fmt.Println(params) fmt.Println(params)
@@ -57,7 +57,7 @@ func main() {
mux := http.NewServeMux() mux := http.NewServeMux()
mux.Handle(notesServer.PathPrefix(), notesServer) mux.Handle(notesServer.PathPrefix(), notesServer)
err := http.ListenAndServe(":8000", notesServer) // not ssrfSink err := http.ListenAndServe(":8000", notesServer) // test: !ssrfSink
if err != nil { if err != nil {
panic(err) panic(err)
} }

View File

@@ -1,2 +1,32 @@
invalidModelRow invalidModelRow
testFailures passingPositiveTests
| PASSED | clientConstructor | rpc/notes/service.twirp.go:53:114:53:139 | comment |
| PASSED | clientConstructor | rpc/notes/service.twirp.go:192:110:192:135 | comment |
| PASSED | message | rpc/notes/service.pb.go:23:20:23:35 | comment |
| PASSED | message | rpc/notes/service.pb.go:86:32:86:47 | comment |
| PASSED | message | rpc/notes/service.pb.go:133:33:133:48 | comment |
| PASSED | message | rpc/notes/service.pb.go:171:33:171:48 | comment |
| PASSED | request | server/main.go:19:111:19:140 | comment |
| PASSED | request | server/main.go:40:126:40:155 | comment |
| PASSED | serverConstructor | rpc/notes/service.twirp.go:334:81:334:106 | comment |
| PASSED | serviceClient | rpc/notes/service.twirp.go:44:42:44:63 | comment |
| PASSED | serviceClient | rpc/notes/service.twirp.go:183:38:183:59 | comment |
| PASSED | serviceInterface | rpc/notes/service.twirp.go:34:31:34:55 | comment |
| PASSED | serviceServer | rpc/notes/service.twirp.go:322:34:322:55 | comment |
| PASSED | ssrf | server/main.go:30:97:30:119 | comment |
| PASSED | ssrfSink | client/main.go:12:89:12:105 | comment |
| PASSED | ssrfSink | server/main.go:30:97:30:119 | comment |
| PASSED | ssrfSink | server/main.go:31:97:31:120 | comment |
failingPositiveTests
passingNegativeTests
| PASSED | !handler | rpc/notes/service.twirp.go:87:109:87:125 | comment |
| PASSED | !handler | rpc/notes/service.twirp.go:116:113:116:129 | comment |
| PASSED | !handler | rpc/notes/service.twirp.go:133:124:133:140 | comment |
| PASSED | !handler | rpc/notes/service.twirp.go:162:128:162:144 | comment |
| PASSED | !handler | rpc/notes/service.twirp.go:226:105:226:121 | comment |
| PASSED | !handler | rpc/notes/service.twirp.go:255:109:255:125 | comment |
| PASSED | !handler | rpc/notes/service.twirp.go:272:120:272:136 | comment |
| PASSED | !handler | rpc/notes/service.twirp.go:301:124:301:140 | comment |
| PASSED | !ssrf | server/main.go:31:97:31:120 | comment |
| PASSED | !ssrfSink | server/main.go:60:51:60:68 | comment |
failingNegativeTests

View File

@@ -2,76 +2,181 @@ import go
import semmle.go.dataflow.ExternalFlow import semmle.go.dataflow.ExternalFlow
import ModelValidation import ModelValidation
import semmle.go.security.RequestForgery import semmle.go.security.RequestForgery
import utils.test.InlineExpectationsTest
module TwirpTest implements TestSig { class InlineTest extends LineComment {
string getARelevantTag() { string tests;
result =
[ InlineTest() { tests = this.getText().regexpCapture("\\s*test:(.*)", 1) }
"handler", "request", "ssrfSink", "message", "serviceInterface", "serviceClient",
"serviceServer", "clientConstructor", "serverConstructor", "ssrf" string getPositiveTest() {
] result = tests.trim().splitAt(",").trim() and not result.matches("!%")
} }
additional predicate hasEntityResult(Location location, string element, Entity entity) { string getNegativeTest() { result = tests.trim().splitAt(",").trim() and result.matches("!%") }
location = entity.getDeclaration().getLocation() and
element = entity.toString() predicate hasPositiveTest(string test) { test = this.getPositiveTest() }
predicate hasNegativeTest(string test) { test = this.getNegativeTest() }
predicate inNode(DataFlow::Node n) {
this.getLocation().getFile() = n.getFile() and
this.getLocation().getStartLine() = n.getStartLine()
} }
additional predicate hasTypeResult(Location location, string element, Type goType) { predicate inEntity(Entity e) {
exists(TypeEntity typeEntity | this.getLocation().getFile() = e.getDeclaration().getFile() and
typeEntity.getType() = goType and this.getLocation().getStartLine() = e.getDeclaration().getLocation().getStartLine()
location = typeEntity.getDeclaration().getLocation() and
element = goType.toString()
)
} }
predicate hasActualResult(Location location, string element, string tag, string value) { predicate inType(Type t) {
value = "" and exists(TypeEntity te |
( te.getType() = t and
tag = "handler" and this.getLocation().getFile() = te.getDeclaration().getFile() and
exists(Twirp::ServiceHandler handler | hasEntityResult(location, element, handler)) this.getLocation().getStartLine() = te.getDeclaration().getLocation().getStartLine()
or
tag = "request" and
exists(Twirp::Request request |
location = request.getLocation() and
element = request.toString()
)
or
tag = "ssrfSink" and
exists(RequestForgery::Sink sink |
location = sink.getLocation() and
element = sink.toString()
)
or
tag = "message" and
exists(Twirp::ProtobufMessageType message | hasTypeResult(location, element, message))
or
tag = "serviceInterface" and
exists(Twirp::ServiceInterfaceType serviceInterface |
hasTypeResult(location, element, serviceInterface.getDefinedType())
)
or
tag = "serviceClient" and
exists(Twirp::ServiceClientType client | hasTypeResult(location, element, client))
or
tag = "serviceServer" and
exists(Twirp::ServiceServerType server | hasTypeResult(location, element, server))
or
tag = "clientConstructor" and
exists(Twirp::ClientConstructor constructor | hasEntityResult(location, element, constructor))
or
tag = "serverConstructor" and
exists(Twirp::ServerConstructor constructor | hasEntityResult(location, element, constructor))
or
tag = "ssrf" and
exists(DataFlow::Node sink |
RequestForgery::Flow::flowTo(sink) and
location = sink.getLocation() and
element = sink.toString()
)
) )
} }
} }
import MakeTest<TwirpTest> query predicate passingPositiveTests(string res, string expectation, InlineTest t) {
res = "PASSED" and
t.hasPositiveTest(expectation) and
(
expectation = "handler" and
exists(Twirp::ServiceHandler n | t.inEntity(n))
or
expectation = "request" and
exists(Twirp::Request n | t.inNode(n))
or
expectation = "ssrfSink" and
exists(RequestForgery::Sink n | t.inNode(n))
or
expectation = "message" and
exists(Twirp::ProtobufMessageType n | t.inType(n))
or
expectation = "serviceInterface" and
exists(Twirp::ServiceInterfaceType n | t.inType(n.getDefinedType()))
or
expectation = "serviceClient" and
exists(Twirp::ServiceClientType n | t.inType(n))
or
expectation = "serviceServer" and
exists(Twirp::ServiceServerType n | t.inType(n))
or
expectation = "clientConstructor" and
exists(Twirp::ClientConstructor n | t.inEntity(n))
or
expectation = "serverConstructor" and
exists(Twirp::ServerConstructor n | t.inEntity(n))
or
expectation = "ssrf" and
exists(DataFlow::Node sink | RequestForgery::Flow::flowTo(sink) and t.inNode(sink))
)
}
query predicate failingPositiveTests(string res, string expectation, InlineTest t) {
res = "FAILED" and
t.hasPositiveTest(expectation) and
(
expectation = "handler" and
not exists(Twirp::ServiceHandler n | t.inEntity(n))
or
expectation = "request" and
not exists(Twirp::Request n | t.inNode(n))
or
expectation = "ssrfSink" and
not exists(RequestForgery::Sink n | t.inNode(n))
or
expectation = "message" and
not exists(Twirp::ProtobufMessageType n | t.inType(n))
or
expectation = "serviceInterface" and
not exists(Twirp::ServiceInterfaceType n | t.inType(n.getDefinedType()))
or
expectation = "serviceClient" and
not exists(Twirp::ServiceClientType n | t.inType(n))
or
expectation = "serviceServer" and
not exists(Twirp::ServiceServerType n | t.inType(n))
or
expectation = "clientConstructor" and
not exists(Twirp::ClientConstructor n | t.inEntity(n))
or
expectation = "serverConstructor" and
not exists(Twirp::ServerConstructor n | t.inEntity(n))
or
expectation = "ssrf" and
not exists(DataFlow::Node sink | RequestForgery::Flow::flowTo(sink) and t.inNode(sink))
)
}
query predicate passingNegativeTests(string res, string expectation, InlineTest t) {
res = "PASSED" and
t.hasNegativeTest(expectation) and
(
expectation = "!handler" and
not exists(Twirp::ServiceHandler n | t.inEntity(n))
or
expectation = "!request" and
not exists(Twirp::Request n | t.inNode(n))
or
expectation = "!ssrfSink" and
not exists(RequestForgery::Sink n | t.inNode(n))
or
expectation = "!message" and
not exists(Twirp::ProtobufMessageType n | t.inType(n))
or
expectation = "!serviceInterface" and
not exists(Twirp::ServiceInterfaceType n | t.inType(n))
or
expectation = "!serviceClient" and
not exists(Twirp::ServiceClientType n | t.inType(n))
or
expectation = "!serviceServer" and
not exists(Twirp::ServiceServerType n | t.inType(n))
or
expectation = "!clientConstructor" and
not exists(Twirp::ClientConstructor n | t.inEntity(n))
or
expectation = "!serverConstructor" and
not exists(Twirp::ServerConstructor n | t.inEntity(n))
or
expectation = "!ssrf" and
not exists(DataFlow::Node sink | RequestForgery::Flow::flowTo(sink) and t.inNode(sink))
)
}
query predicate failingNegativeTests(string res, string expectation, InlineTest t) {
res = "FAILED" and
t.hasNegativeTest(expectation) and
(
expectation = "!handler" and
exists(Twirp::ServiceHandler n | t.inEntity(n))
or
expectation = "!request" and
exists(Twirp::Request n | t.inNode(n))
or
expectation = "!ssrfSink" and
exists(RequestForgery::Sink n | t.inNode(n))
or
expectation = "!message" and
exists(Twirp::ProtobufMessageType n | t.inType(n))
or
expectation = "!serviceInterface" and
exists(Twirp::ServiceInterfaceType n | t.inType(n))
or
expectation = "!serviceClient" and
exists(Twirp::ServiceClientType n | t.inType(n))
or
expectation = "!serviceServer" and
exists(Twirp::ServiceServerType n | t.inType(n))
or
expectation = "!clientConstructor" and
exists(Twirp::ClientConstructor n | t.inEntity(n))
or
expectation = "!serverConstructor" and
exists(Twirp::ServerConstructor n | t.inEntity(n))
or
expectation = "!ssrf" and
exists(DataFlow::Node sink | RequestForgery::Flow::flowTo(sink) and t.inNode(sink))
)
}

View File

@@ -1,4 +1,2 @@
query: Security/CWE-079/ReflectedXss.ql query: Security/CWE-079/ReflectedXss.ql
postprocess: postprocess: utils/test/PrettyPrintModels.ql
- utils/test/PrettyPrintModels.ql
- utils/test/InlineExpectationsTestQuery.ql

View File

@@ -1,4 +1,2 @@
query: Security/CWE-089/SqlInjection.ql query: Security/CWE-089/SqlInjection.ql
postprocess: postprocess: utils/test/PrettyPrintModels.ql
- utils/test/PrettyPrintModels.ql
- utils/test/InlineExpectationsTestQuery.ql

View File

@@ -9,50 +9,50 @@ import (
func test(request *http.Request, writer http.ResponseWriter) { func test(request *http.Request, writer http.ResponseWriter) {
param1 := request.URL.Query().Get("param1") // $ Source[go/reflected-xss] param1 := request.URL.Query().Get("param1")
writer.Write([]byte(html.EscapeString(param1))) // GOOD: escaped. writer.Write([]byte(html.EscapeString(param1))) // GOOD: escaped.
writer.Write([]byte(html.UnescapeString(param1))) // $ Alert[go/reflected-xss] // BAD: unescaped. writer.Write([]byte(html.UnescapeString(param1))) // BAD: unescaped.
node, _ := html.Parse(request.Body) // $ Source[go/reflected-xss] node, _ := html.Parse(request.Body)
writer.Write([]byte(node.Data)) // $ Alert[go/reflected-xss] // BAD: writing unescaped HTML data writer.Write([]byte(node.Data)) // BAD: writing unescaped HTML data
node2, _ := html.ParseWithOptions(request.Body) // $ Source[go/reflected-xss] node2, _ := html.ParseWithOptions(request.Body)
writer.Write([]byte(node2.Data)) // $ Alert[go/reflected-xss] // BAD: writing unescaped HTML data writer.Write([]byte(node2.Data)) // BAD: writing unescaped HTML data
nodes, _ := html.ParseFragment(request.Body, nil) // $ Source[go/reflected-xss] nodes, _ := html.ParseFragment(request.Body, nil)
writer.Write([]byte(nodes[0].Data)) // $ Alert[go/reflected-xss] // BAD: writing unescaped HTML data writer.Write([]byte(nodes[0].Data)) // BAD: writing unescaped HTML data
nodes2, _ := html.ParseFragmentWithOptions(request.Body, nil) // $ Source[go/reflected-xss] nodes2, _ := html.ParseFragmentWithOptions(request.Body, nil)
writer.Write([]byte(nodes2[0].Data)) // $ Alert[go/reflected-xss] // BAD: writing unescaped HTML data writer.Write([]byte(nodes2[0].Data)) // BAD: writing unescaped HTML data
html.Render(writer, node) // $ Alert[go/reflected-xss] // BAD: rendering untrusted HTML to `writer` html.Render(writer, node) // BAD: rendering untrusted HTML to `writer`
tokenizer := html.NewTokenizer(request.Body) // $ Source[go/reflected-xss] tokenizer := html.NewTokenizer(request.Body)
writer.Write(tokenizer.Buffered()) // $ Alert[go/reflected-xss] // BAD: writing unescaped HTML data writer.Write(tokenizer.Buffered()) // BAD: writing unescaped HTML data
writer.Write(tokenizer.Raw()) // $ Alert[go/reflected-xss] // BAD: writing unescaped HTML data writer.Write(tokenizer.Raw()) // BAD: writing unescaped HTML data
_, value, _ := tokenizer.TagAttr() _, value, _ := tokenizer.TagAttr()
writer.Write(value) // $ Alert[go/reflected-xss] // BAD: writing unescaped HTML data writer.Write(value) // BAD: writing unescaped HTML data
writer.Write(tokenizer.Text()) // $ Alert[go/reflected-xss] // BAD: writing unescaped HTML data writer.Write(tokenizer.Text()) // BAD: writing unescaped HTML data
writer.Write([]byte(tokenizer.Token().Data)) // $ Alert[go/reflected-xss] // BAD: writing unescaped HTML data writer.Write([]byte(tokenizer.Token().Data)) // BAD: writing unescaped HTML data
tokenizerFragment := html.NewTokenizerFragment(request.Body, "some context") // $ Source[go/reflected-xss] tokenizerFragment := html.NewTokenizerFragment(request.Body, "some context")
writer.Write(tokenizerFragment.Buffered()) // $ Alert[go/reflected-xss] // BAD: writing unescaped HTML data writer.Write(tokenizerFragment.Buffered()) // BAD: writing unescaped HTML data
var cleanNode html.Node var cleanNode html.Node
taintedNode, _ := html.Parse(request.Body) // $ Source[go/reflected-xss] taintedNode, _ := html.Parse(request.Body)
cleanNode.AppendChild(taintedNode) cleanNode.AppendChild(taintedNode)
html.Render(writer, &cleanNode) // $ Alert[go/reflected-xss] // BAD: writing unescaped HTML data html.Render(writer, &cleanNode) // BAD: writing unescaped HTML data
var cleanNode2 html.Node var cleanNode2 html.Node
taintedNode2, _ := html.Parse(request.Body) // $ Source[go/reflected-xss] taintedNode2, _ := html.Parse(request.Body)
cleanNode2.InsertBefore(taintedNode2, &cleanNode2) cleanNode2.InsertBefore(taintedNode2, &cleanNode2)
html.Render(writer, &cleanNode2) // $ Alert[go/reflected-xss] // BAD: writing unescaped HTML data html.Render(writer, &cleanNode2) // BAD: writing unescaped HTML data
} }
func sqlTest(request *http.Request, db *sql.DB) { func sqlTest(request *http.Request, db *sql.DB) {
// Ensure EscapeString is a taint propagator for non-XSS queries, e.g. SQL injection: // Ensure EscapeString is a taint propagator for non-XSS queries, e.g. SQL injection:
cookie, _ := request.Cookie("SomeCookie") // $ Source[go/sql-injection] cookie, _ := request.Cookie("SomeCookie")
db.Query(html.EscapeString(cookie.Value)) // $ Alert[go/sql-injection] db.Query(html.EscapeString(cookie.Value))
} }

View File

@@ -2,7 +2,7 @@ package main
func isPrefixOf(xs, ys []int) bool { func isPrefixOf(xs, ys []int) bool {
for i := 0; i < len(xs); i++ { for i := 0; i < len(xs); i++ {
if len(ys) == 0 || xs[i] != ys[i] { // $ Alert // NOT OK if len(ys) == 0 || xs[i] != ys[i] { // NOT OK
return false return false
} }
} }

View File

@@ -1,2 +1 @@
query: InconsistentCode/ConstantLengthComparison.ql InconsistentCode/ConstantLengthComparison.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -7,7 +7,7 @@ func zeroOutExceptBad(a []int, lower int, upper int) {
} }
// zero out everything above index `upper` // zero out everything above index `upper`
for i := upper + 1; i < len(a); i-- { // $ Alert // NOT OK for i := upper + 1; i < len(a); i-- { // NOT OK
a[i] = 0 a[i] = 0
} }
} }

View File

@@ -1,2 +1 @@
query: InconsistentCode/InconsistentLoopOrientation.ql InconsistentCode/InconsistentLoopOrientation.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -6,12 +6,12 @@ func f1(i int) {
} }
func f2(i int, s string) { func f2(i int, s string) {
for j := i + 1; j < len(s); j-- { // $ Alert // NOT OK for j := i + 1; j < len(s); j-- { // NOT OK
} }
} }
func f3(s string) { func f3(s string) {
for i, l := 0, len(s); i > l; i++ { // $ Alert // NOT OK for i, l := 0, len(s); i > l; i++ { // NOT OK
} }
} }
@@ -22,7 +22,7 @@ func f4(lower int, a []int) {
} }
func f5(upper int, a []int) { func f5(upper int, a []int) {
for i := upper + 1; i < len(a); i-- { // $ Alert // NOT OK for i := upper + 1; i < len(a); i-- { // NOT OK
a[i] = 0 a[i] = 0
} }
} }

View File

@@ -5,9 +5,9 @@ import "strings"
func containsBad(searchName string, names string) bool { func containsBad(searchName string, names string) bool {
values := strings.Split(names, ",") values := strings.Split(names, ",")
// BAD: index could be equal to length // BAD: index could be equal to length
for i := 0; i <= len(values); i++ { // $ Alert for i := 0; i <= len(values); i++ {
// When i = length, this access will be out of bounds // When i = length, this access will be out of bounds
if values[i] == searchName { // $ Source if values[i] == searchName {
return true return true
} }
} }

View File

@@ -1,2 +1 @@
query: InconsistentCode/LengthComparisonOffByOne.ql InconsistentCode/LengthComparisonOffByOne.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -3,8 +3,8 @@ package main
import "regexp" import "regexp"
func f1(i int, a []int) int { func f1(i int, a []int) int {
if i <= len(a) { // $ Alert // NOT OK if i <= len(a) { // NOT OK
return a[i] // $ Source return a[i]
} }
return -1 return -1
} }
@@ -26,8 +26,8 @@ func f3(i int, a []int) int {
} }
func f4(i int, a []int) int { func f4(i int, a []int) int {
if len(a) > 0 { // $ Alert // NOT OK if len(a) > 0 { // NOT OK
return a[1] // $ Source return a[1]
} }
return -1 return -1
} }

View File

@@ -1,2 +1 @@
query: InconsistentCode/MissingErrorCheck.ql InconsistentCode/MissingErrorCheck.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -58,7 +58,7 @@ func missingCheckMayFail(fname string) {
result, err := os.Open(fname) result, err := os.Open(fname)
fmt.Printf("Opened: %v\n", *result) // $ Alert // NOT OK fmt.Printf("Opened: %v\n", *result) // NOT OK
fmt.Printf("%v\n", err) // use err fmt.Printf("%v\n", err) // use err
} }
@@ -240,7 +240,7 @@ func mishandlesMyError(input int) {
result, err := returnsMyError(input) result, err := returnsMyError(input)
fmt.Printf("Got: %d\n", *result) // $ Alert // NOT OK fmt.Printf("Got: %d\n", *result) // NOT OK
fmt.Printf("%v\n", err) // use err fmt.Printf("%v\n", err) // use err
} }

View File

@@ -3,5 +3,5 @@ package main
import "fmt" import "fmt"
func test() { func test() {
fmt.Println(2 ^ 32) // $ Alert // should be 1 << 32 fmt.Println(2 ^ 32) // should be 1 << 32
} }

View File

@@ -1,2 +1 @@
query: InconsistentCode/MistypedExponentiation.ql InconsistentCode/MistypedExponentiation.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -12,13 +12,13 @@ func main() {
expectingResponse := 1 << 5 expectingResponse := 1 << 5
power := 10 power := 10
fmt.Println(3 ^ 5) // $ Alert // Not OK fmt.Println(3 ^ 5) // Not OK
fmt.Println(0755 ^ 2423) // OK fmt.Println(0755 ^ 2423) // OK
fmt.Println(2 ^ 32) // $ Alert // Not OK fmt.Println(2 ^ 32) // Not OK
fmt.Println(10 ^ 5) // $ Alert // Not OK fmt.Println(10 ^ 5) // Not OK
fmt.Println(10 ^ exp) // $ Alert // Not OK fmt.Println(10 ^ exp) // Not OK
fmt.Println(253 ^ expectingResponse) // OK fmt.Println(253 ^ expectingResponse) // OK
fmt.Println(2 ^ power) // $ Alert // Not OK fmt.Println(2 ^ power) // Not OK
mask := (((1 << 10) - 1) ^ 7) // OK mask := (((1 << 10) - 1) ^ 7) // OK

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