mirror of
https://github.com/securego/gosec.git
synced 2024-12-25 03:55:54 +00:00
Add support for math/rand/v2 added in Go 1.22
This commit is contained in:
parent
36878a9423
commit
be378e682f
3 changed files with 109 additions and 10 deletions
|
@ -15,9 +15,14 @@ package gosec
|
||||||
import (
|
import (
|
||||||
"go/ast"
|
"go/ast"
|
||||||
"go/types"
|
"go/types"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
versioningPackagePattern = regexp.MustCompile(`v[0-9]+$`)
|
||||||
|
)
|
||||||
|
|
||||||
// ImportTracker is used to normalize the packages that have been imported
|
// ImportTracker is used to normalize the packages that have been imported
|
||||||
// by a source file. It is able to differentiate between plain imports, aliased
|
// by a source file. It is able to differentiate between plain imports, aliased
|
||||||
// imports and init only imports.
|
// imports and init only imports.
|
||||||
|
@ -66,5 +71,10 @@ func importName(importPath string) string {
|
||||||
if len(parts) > 0 {
|
if len(parts) > 0 {
|
||||||
name = parts[len(parts)-1]
|
name = parts[len(parts)-1]
|
||||||
}
|
}
|
||||||
|
// If the last segment of the path is version information, consider the second to last segment as the package name.
|
||||||
|
// (e.g., `math/rand/v2` would be `rand`)
|
||||||
|
if len(parts) > 1 && versioningPackagePattern.MatchString(name) {
|
||||||
|
name = parts[len(parts)-2]
|
||||||
|
}
|
||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,8 +23,7 @@ import (
|
||||||
|
|
||||||
type weakRand struct {
|
type weakRand struct {
|
||||||
issue.MetaData
|
issue.MetaData
|
||||||
funcNames []string
|
blocklist map[string][]string
|
||||||
packagePath string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *weakRand) ID() string {
|
func (w *weakRand) ID() string {
|
||||||
|
@ -32,8 +31,8 @@ func (w *weakRand) ID() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *weakRand) Match(n ast.Node, c *gosec.Context) (*issue.Issue, error) {
|
func (w *weakRand) Match(n ast.Node, c *gosec.Context) (*issue.Issue, error) {
|
||||||
for _, funcName := range w.funcNames {
|
for pkg, funcs := range w.blocklist {
|
||||||
if _, matched := gosec.MatchCallByPackage(n, c, w.packagePath, funcName); matched {
|
if _, matched := gosec.MatchCallByPackage(n, c, pkg, funcs...); matched {
|
||||||
return c.NewIssue(n, w.ID(), w.What, w.Severity, w.Confidence), nil
|
return c.NewIssue(n, w.ID(), w.What, w.Severity, w.Confidence), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,17 +42,22 @@ func (w *weakRand) Match(n ast.Node, c *gosec.Context) (*issue.Issue, error) {
|
||||||
|
|
||||||
// NewWeakRandCheck detects the use of random number generator that isn't cryptographically secure
|
// NewWeakRandCheck detects the use of random number generator that isn't cryptographically secure
|
||||||
func NewWeakRandCheck(id string, _ gosec.Config) (gosec.Rule, []ast.Node) {
|
func NewWeakRandCheck(id string, _ gosec.Config) (gosec.Rule, []ast.Node) {
|
||||||
|
calls := make(map[string][]string)
|
||||||
|
calls["math/rand"] = []string{
|
||||||
|
"New", "Read", "Float32", "Float64", "Int", "Int31", "Int31n",
|
||||||
|
"Int63", "Int63n", "Intn", "NormFloat64", "Uint32", "Uint64",
|
||||||
|
}
|
||||||
|
calls["math/rand/v2"] = []string{
|
||||||
|
"New", "Float32", "Float64", "Int", "Int32", "Int32N",
|
||||||
|
"Int64", "Int64N", "IntN", "N", "NormFloat64", "Uint32", "Uint32N", "Uint64", "Uint64N", "UintN",
|
||||||
|
}
|
||||||
return &weakRand{
|
return &weakRand{
|
||||||
funcNames: []string{
|
blocklist: calls,
|
||||||
"New", "Read", "Float32", "Float64", "Int", "Int31",
|
|
||||||
"Int31n", "Int63", "Int63n", "Intn", "NormalFloat64", "Uint32", "Uint64",
|
|
||||||
},
|
|
||||||
packagePath: "math/rand",
|
|
||||||
MetaData: issue.MetaData{
|
MetaData: issue.MetaData{
|
||||||
ID: id,
|
ID: id,
|
||||||
Severity: issue.High,
|
Severity: issue.High,
|
||||||
Confidence: issue.Medium,
|
Confidence: issue.Medium,
|
||||||
What: "Use of weak random number generator (math/rand instead of crypto/rand)",
|
What: "Use of weak random number generator (math/rand or math/rand/v2 instead of crypto/rand)",
|
||||||
},
|
},
|
||||||
}, []ast.Node{(*ast.CallExpr)(nil)}
|
}, []ast.Node{(*ast.CallExpr)(nil)}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,16 @@ func main() {
|
||||||
{[]string{`
|
{[]string{`
|
||||||
package main
|
package main
|
||||||
|
|
||||||
|
import "math/rand/v2"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
bad := rand.Int()
|
||||||
|
println(bad)
|
||||||
|
}
|
||||||
|
`}, 1, gosec.NewConfig()},
|
||||||
|
{[]string{`
|
||||||
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
mrand "math/rand"
|
mrand "math/rand"
|
||||||
|
@ -42,6 +52,21 @@ func main() {
|
||||||
{[]string{`
|
{[]string{`
|
||||||
package main
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
mrand "math/rand/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
good, _ := rand.Read(nil)
|
||||||
|
println(good)
|
||||||
|
bad := mrand.Int32()
|
||||||
|
println(bad)
|
||||||
|
}
|
||||||
|
`}, 1, gosec.NewConfig()},
|
||||||
|
{[]string{`
|
||||||
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math/rand"
|
"math/rand"
|
||||||
)
|
)
|
||||||
|
@ -55,6 +80,19 @@ func main() {
|
||||||
{[]string{`
|
{[]string{`
|
||||||
package main
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/rand/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
gen := rand.New(rand.NewPCG(1, 2))
|
||||||
|
bad := gen.Int()
|
||||||
|
println(bad)
|
||||||
|
}
|
||||||
|
`}, 1, gosec.NewConfig()},
|
||||||
|
{[]string{`
|
||||||
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math/rand"
|
"math/rand"
|
||||||
)
|
)
|
||||||
|
@ -67,6 +105,18 @@ func main() {
|
||||||
{[]string{`
|
{[]string{`
|
||||||
package main
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/rand/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
bad := rand.IntN(10)
|
||||||
|
println(bad)
|
||||||
|
}
|
||||||
|
`}, 1, gosec.NewConfig()},
|
||||||
|
{[]string{`
|
||||||
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
@ -83,6 +133,22 @@ func main() {
|
||||||
{[]string{`
|
{[]string{`
|
||||||
package main
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"math/big"
|
||||||
|
rnd "math/rand/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
good, _ := rand.Int(rand.Reader, big.NewInt(int64(2)))
|
||||||
|
println(good)
|
||||||
|
bad := rnd.IntN(2)
|
||||||
|
println(bad)
|
||||||
|
}
|
||||||
|
`}, 1, gosec.NewConfig()},
|
||||||
|
{[]string{`
|
||||||
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
crand "crypto/rand"
|
crand "crypto/rand"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
@ -98,5 +164,24 @@ func main() {
|
||||||
_ = rand2.Intn(2) // bad
|
_ = rand2.Intn(2) // bad
|
||||||
_ = rand3.Intn(2) // bad
|
_ = rand3.Intn(2) // bad
|
||||||
}
|
}
|
||||||
|
`}, 3, gosec.NewConfig()},
|
||||||
|
{[]string{`
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
crand "crypto/rand"
|
||||||
|
"math/big"
|
||||||
|
"math/rand/v2"
|
||||||
|
rand2 "math/rand/v2"
|
||||||
|
rand3 "math/rand/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
_, _ = crand.Int(crand.Reader, big.NewInt(int64(2))) // good
|
||||||
|
|
||||||
|
_ = rand.IntN(2) // bad
|
||||||
|
_ = rand2.IntN(2) // bad
|
||||||
|
_ = rand3.IntN(2) // bad
|
||||||
|
}
|
||||||
`}, 3, gosec.NewConfig()},
|
`}, 3, gosec.NewConfig()},
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue