From dfde579243e1bfe0856ddafc5fc6aebb29c0edf6 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Sun, 4 Sep 2022 16:32:03 +0200 Subject: [PATCH] Fix false positives for G404 with aliased packages It appears that `GetImportedName` returns _both_ aliased and non-aliased imports. As a result, a file having both crypto/rand and math/rand (but aliased) would trigger false positives on G404. Given the following file; ```go package main import ( "crypto/rand" "math/big" rnd "math/rand" ) func main() { _, _ = rand.Int(rand.Reader, big.NewInt(int64(2))) _ = rnd.Intn(2) } ``` And patching for debugging; ```patch diff --git a/helpers.go b/helpers.go index 437d032..80f4233 100644 --- a/helpers.go +++ b/helpers.go @@ -250,6 +250,8 @@ func GetBinaryExprOperands(be *ast.BinaryExpr) []ast.Node { // GetImportedName returns the name used for the package within the // code. It will ignore initialization only imports. func GetImportedName(path string, ctx *Context) (string, bool) { + fmt.Printf("%+v", ctx.Imports.Imported) + os.Exit(1) importName, imported := ctx.Imports.Imported[path] if !imported { return "", false ``` Would show that `math/rand` was included in the list, using it's non-aliased name (`:rand`). gosec -quiet . map[crypto/rand:rand math/big:big math/rand:rand] This patch works around this problem by reversing the order in which imports are resolved in `MatchCallByPackage()`. Aliased packages are tried first, after which non-aliased imports are tried. Given the example application mentioned above: Before this patch: ```bash gosec -quiet . Results: [/Users/sebastiaan/Projects/test/gosec-issue/main.go:10] - G404 (CWE-338): Use of weak random number generator (math/rand instead of crypto/rand) (Confidence: MEDIUM, Severity: HIGH) 9: func main() { > 10: _, _ = rand.Int(rand.Reader, big.NewInt(int64(2))) 11: _ = rnd.Intn(2) ``` With this patch applied: ```bash gosec --quiet . Results: [/Users/sebastiaan/Projects/test/gosec-issue/main.go:11] - G404 (CWE-338): Use of weak random number generator (math/rand instead of crypto/rand) (Confidence: MEDIUM, Severity: HIGH) 10: _, _ = rand.Int(rand.Reader, big.NewInt(int64(2))) > 11: _ = rnd.Intn(2) 12: } ``` Signed-off-by: Sebastiaan van Stijn --- helpers.go | 4 ++-- testutils/source.go | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/helpers.go b/helpers.go index 437d032..bd6aff7 100644 --- a/helpers.go +++ b/helpers.go @@ -37,9 +37,9 @@ import ( // // node, matched := MatchCallByPackage(n, ctx, "math/rand", "Read") func MatchCallByPackage(n ast.Node, c *Context, pkg string, names ...string) (*ast.CallExpr, bool) { - importedName, found := GetImportedName(pkg, c) + importedName, found := GetAliasedName(pkg, c) if !found { - importedName, found = GetAliasedName(pkg, c) + importedName, found = GetImportedName(pkg, c) if !found { return nil, false } diff --git a/testutils/source.go b/testutils/source.go index e1124a4..3db02e2 100644 --- a/testutils/source.go +++ b/testutils/source.go @@ -3180,6 +3180,22 @@ func main() { bad := rand.Intn(10) println(bad) }`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "crypto/rand" + "math/big" + rnd "math/rand" +) + +func main() { + good, _ := rand.Int(rand.Reader, big.NewInt(int64(2))) + println(good) + bad := rnd.Intn(2) + println(bad) +} +`}, 1, gosec.NewConfig()}, } // SampleCodeG501 - Blocklisted import MD5