mirror of
https://github.com/securego/gosec.git
synced 2026-01-15 01:33:41 +08:00
feat(rules): add support for detecting high entropy strings in composite literals (#1447)
This commit is contained in:
@@ -229,6 +229,8 @@ func (r *credentials) Match(n ast.Node, ctx *gosec.Context) (*issue.Issue, error
|
||||
return r.matchValueSpec(node, ctx)
|
||||
case *ast.BinaryExpr:
|
||||
return r.matchEqualityCheck(node, ctx)
|
||||
case *ast.CompositeLit:
|
||||
return r.matchCompositeLit(node, ctx)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
@@ -334,6 +336,44 @@ func (r *credentials) matchEqualityCheck(binaryExpr *ast.BinaryExpr, ctx *gosec.
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (r *credentials) matchCompositeLit(lit *ast.CompositeLit, ctx *gosec.Context) (*issue.Issue, error) {
|
||||
for _, elt := range lit.Elts {
|
||||
if kv, ok := elt.(*ast.KeyValueExpr); ok {
|
||||
// Check if the key matches the credential pattern (struct field name or map string literal key)
|
||||
matchedKey := false
|
||||
if ident, ok := kv.Key.(*ast.Ident); ok {
|
||||
if r.pattern.MatchString(ident.Name) {
|
||||
matchedKey = true
|
||||
}
|
||||
}
|
||||
if keyStr, err := gosec.GetString(kv.Key); err == nil {
|
||||
if r.pattern.MatchString(keyStr) {
|
||||
matchedKey = true
|
||||
}
|
||||
}
|
||||
|
||||
// If key matches, check value for high entropy (generic credential warning)
|
||||
if matchedKey {
|
||||
if val, err := gosec.GetString(kv.Value); err == nil {
|
||||
if r.ignoreEntropy || r.isHighEntropyString(val) {
|
||||
return ctx.NewIssue(lit, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Separately check value for specific secret patterns (regardless of key)
|
||||
if val, err := gosec.GetString(kv.Value); err == nil {
|
||||
if r.ignoreEntropy || r.isHighEntropyString(val) {
|
||||
if ok, patternName := r.isSecretPattern(val); ok {
|
||||
return ctx.NewIssue(lit, r.ID(), fmt.Sprintf("%s: %s", r.What, patternName), r.Severity, r.Confidence), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// NewHardcodedCredentials attempts to find high entropy string constants being
|
||||
// assigned to variables that appear to be related to credentials.
|
||||
func NewHardcodedCredentials(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
@@ -390,5 +430,5 @@ func NewHardcodedCredentials(id string, conf gosec.Config) (gosec.Rule, []ast.No
|
||||
Confidence: issue.Low,
|
||||
Severity: issue.High,
|
||||
},
|
||||
}, []ast.Node{(*ast.AssignStmt)(nil), (*ast.ValueSpec)(nil), (*ast.BinaryExpr)(nil)}
|
||||
}, []ast.Node{(*ast.AssignStmt)(nil), (*ast.ValueSpec)(nil), (*ast.BinaryExpr)(nil), (*ast.CompositeLit)(nil)}
|
||||
}
|
||||
|
||||
@@ -364,7 +364,123 @@ const (
|
||||
func main() {
|
||||
fmt.Printf("%s\n", ConfigLearnerTokenAuth)
|
||||
}
|
||||
|
||||
|
||||
`}, 0, gosec.NewConfig()},
|
||||
{[]string{`
|
||||
package main
|
||||
|
||||
type DBConfig struct {
|
||||
Password string
|
||||
}
|
||||
|
||||
func main() {
|
||||
_ = DBConfig{
|
||||
Password: "f62e5bcda4fae4f82370da0c6f20697b8f8447ef",
|
||||
}
|
||||
}
|
||||
`}, 1, gosec.NewConfig()},
|
||||
{[]string{`
|
||||
package main
|
||||
|
||||
type DBConfig struct {
|
||||
Password string
|
||||
}
|
||||
|
||||
func main() {
|
||||
_ = &DBConfig{
|
||||
Password: "f62e5bcda4fae4f82370da0c6f20697b8f8447ef",
|
||||
}
|
||||
}
|
||||
`}, 1, gosec.NewConfig()},
|
||||
{[]string{`
|
||||
package main
|
||||
|
||||
func main() {
|
||||
_ = struct{ Password string }{
|
||||
Password: "f62e5bcda4fae4f82370da0c6f20697b8f8447ef",
|
||||
}
|
||||
}
|
||||
`}, 1, gosec.NewConfig()},
|
||||
{[]string{`
|
||||
package main
|
||||
|
||||
func main() {
|
||||
_ = map[string]string{
|
||||
"password": "f62e5bcda4fae4f82370da0c6f20697b8f8447ef",
|
||||
}
|
||||
}
|
||||
`}, 1, gosec.NewConfig()},
|
||||
{[]string{`
|
||||
package main
|
||||
|
||||
func main() {
|
||||
_ = map[string]string{
|
||||
"apiKey": "f62e5bcda4fae4f82370da0c6f20697b8f8447ef",
|
||||
}
|
||||
}
|
||||
`}, 1, gosec.NewConfig()},
|
||||
{[]string{`
|
||||
package main
|
||||
|
||||
type Config struct {
|
||||
Username string
|
||||
Password string
|
||||
}
|
||||
|
||||
func main() {
|
||||
_ = Config{
|
||||
Username: "admin",
|
||||
Password: "f62e5bcda4fae4f82370da0c6f20697b8f8447ef",
|
||||
}
|
||||
}
|
||||
`}, 1, gosec.NewConfig()},
|
||||
{[]string{`
|
||||
package main
|
||||
|
||||
type DBConfig struct {
|
||||
Password string
|
||||
}
|
||||
|
||||
func main() {
|
||||
_ = DBConfig{ // #nosec G101
|
||||
Password: "f62e5bcda4fae4f82370da0c6f20697b8f8447ef",
|
||||
}
|
||||
}
|
||||
`}, 0, gosec.NewConfig()},
|
||||
// Negatives
|
||||
{[]string{`
|
||||
package main
|
||||
|
||||
func main() {
|
||||
_ = struct{ Password string }{
|
||||
Password: "secret", // low entropy
|
||||
}
|
||||
}
|
||||
`}, 0, gosec.NewConfig()},
|
||||
{[]string{`
|
||||
package main
|
||||
|
||||
func main() {
|
||||
_ = map[string]string{
|
||||
"password": "secret", // low entropy
|
||||
}
|
||||
}
|
||||
`}, 0, gosec.NewConfig()},
|
||||
{[]string{`
|
||||
package main
|
||||
|
||||
func main() {
|
||||
_ = struct{ Username string }{
|
||||
Username: "f62e5bcda4fae4f82370da0c6f20697b8f8447ef", // non-sensitive key
|
||||
}
|
||||
}
|
||||
`}, 0, gosec.NewConfig()},
|
||||
{[]string{`
|
||||
package main
|
||||
|
||||
func main() {
|
||||
_ = []string{"f62e5bcda4fae4f82370da0c6f20697b8f8447ef"} // unkeyed – no trigger
|
||||
}
|
||||
`}, 0, gosec.NewConfig()},
|
||||
}
|
||||
|
||||
@@ -430,6 +546,24 @@ func main() {
|
||||
if compareGoogleAPI == "AIzajtGS_aJGkoiAmSbXzu9I-1eytAi9Lrlh-vT" {
|
||||
fmt.Println(compareGoogleAPI)
|
||||
}
|
||||
}
|
||||
`}, 1, gosec.NewConfig()},
|
||||
{[]string{`
|
||||
package main
|
||||
|
||||
func main() {
|
||||
_ = struct{ SomeKey string }{
|
||||
SomeKey: "AKIAI44QH8DHBEXAMPLE",
|
||||
}
|
||||
}
|
||||
`}, 1, gosec.NewConfig()},
|
||||
{[]string{`
|
||||
package main
|
||||
|
||||
func main() {
|
||||
_ = map[string]string{
|
||||
"github_token": "ghp_iR54dhCYg9Tfmoywi9xLmmKZrrnAw438BYh3",
|
||||
}
|
||||
}
|
||||
`}, 1, gosec.NewConfig()},
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user