Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: G101 match variable values and names #971

Merged
merged 11 commits into from
Jun 15, 2023
49 changes: 49 additions & 0 deletions rules/hardcoded_credentials.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
type credentials struct {
issue.MetaData
pattern *regexp.Regexp
patternValue *regexp.Regexp // Pattern for matching string values (LHS on assign statements)
entropyThreshold float64
perCharThreshold float64
truncate int
Expand Down Expand Up @@ -70,6 +71,7 @@ func (r *credentials) Match(n ast.Node, ctx *gosec.Context) (*issue.Issue, error
func (r *credentials) matchAssign(assign *ast.AssignStmt, ctx *gosec.Context) (*issue.Issue, error) {
for _, i := range assign.Lhs {
if ident, ok := i.(*ast.Ident); ok {
// Match the variable name
if r.pattern.MatchString(ident.Name) {
for _, e := range assign.Rhs {
if val, err := gosec.GetString(e); err == nil {
Expand All @@ -79,12 +81,24 @@ func (r *credentials) matchAssign(assign *ast.AssignStmt, ctx *gosec.Context) (*
}
}
}

// Match the value assigned
for _, e := range assign.Rhs {
if val, err := gosec.GetString(e); err == nil {
morgenm marked this conversation as resolved.
Show resolved Hide resolved
if r.patternValue.MatchString(val) {
if r.ignoreEntropy || (!r.ignoreEntropy && r.isHighEntropyString(val)) {
morgenm marked this conversation as resolved.
Show resolved Hide resolved
return ctx.NewIssue(assign, r.ID(), r.What, r.Severity, r.Confidence), nil
}
}
}
}
}
}
return nil, nil
}

func (r *credentials) matchValueSpec(valueSpec *ast.ValueSpec, ctx *gosec.Context) (*issue.Issue, error) {
// Match name
morgenm marked this conversation as resolved.
Show resolved Hide resolved
for index, ident := range valueSpec.Names {
if r.pattern.MatchString(ident.Name) && valueSpec.Values != nil {
// const foo, bar = "same value"
Expand All @@ -98,11 +112,29 @@ func (r *credentials) matchValueSpec(valueSpec *ast.ValueSpec, ctx *gosec.Contex
}
}
}

// Match values
for _, ident := range valueSpec.Values {
if val, err := gosec.GetString(ident); err == nil {
if r.patternValue.MatchString(val) {
if r.ignoreEntropy || (!r.ignoreEntropy && r.isHighEntropyString(val)) {
morgenm marked this conversation as resolved.
Show resolved Hide resolved
return ctx.NewIssue(valueSpec, r.ID(), r.What, r.Severity, r.Confidence), nil
}
}
}
}

return nil, nil
}

func (r *credentials) matchEqualityCheck(binaryExpr *ast.BinaryExpr, ctx *gosec.Context) (*issue.Issue, error) {
if binaryExpr.Op == token.EQL || binaryExpr.Op == token.NEQ {
identStrConst, okLit := binaryExpr.X.(*ast.BasicLit)
morgenm marked this conversation as resolved.
Show resolved Hide resolved
if !okLit {
identStrConst, okLit = binaryExpr.Y.(*ast.BasicLit)
}

// Match for Ident Name
ident, ok := binaryExpr.X.(*ast.Ident)
if !ok {
ident, _ = binaryExpr.Y.(*ast.Ident)
Expand All @@ -119,6 +151,14 @@ func (r *credentials) matchEqualityCheck(binaryExpr *ast.BinaryExpr, ctx *gosec.
}
}
}
if okLit { // Match for literals
s, err := gosec.GetString(identStrConst)
morgenm marked this conversation as resolved.
Show resolved Hide resolved
if err == nil && r.patternValue.MatchString(s) {
if r.ignoreEntropy || (!r.ignoreEntropy && r.isHighEntropyString(s)) {
morgenm marked this conversation as resolved.
Show resolved Hide resolved
return ctx.NewIssue(binaryExpr, r.ID(), r.What, r.Severity, r.Confidence), nil
}
}
}
}
return nil, nil
}
Expand All @@ -127,6 +167,7 @@ func (r *credentials) matchEqualityCheck(binaryExpr *ast.BinaryExpr, ctx *gosec.
// assigned to variables that appear to be related to credentials.
func NewHardcodedCredentials(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
pattern := `(?i)passwd|pass|password|pwd|secret|token|pw|apiKey|bearer|cred`
patternValue := "^(?i)[a-f0-9]{64}$"
morgenm marked this conversation as resolved.
Show resolved Hide resolved
entropyThreshold := 80.0
perCharThreshold := 3.0
ignoreEntropy := false
Expand All @@ -138,6 +179,13 @@ func NewHardcodedCredentials(id string, conf gosec.Config) (gosec.Rule, []ast.No
pattern = cfgPattern
}
}

if configPatternValue, ok := conf["patternValue"]; ok {
if cfgPatternValue, ok := configPatternValue.(string); ok {
patternValue = cfgPatternValue
}
}

if configIgnoreEntropy, ok := conf["ignore_entropy"]; ok {
if cfgIgnoreEntropy, ok := configIgnoreEntropy.(bool); ok {
ignoreEntropy = cfgIgnoreEntropy
Expand Down Expand Up @@ -168,6 +216,7 @@ func NewHardcodedCredentials(id string, conf gosec.Config) (gosec.Rule, []ast.No

return &credentials{
pattern: regexp.MustCompile(pattern),
patternValue: regexp.MustCompile(patternValue),
entropyThreshold: entropyThreshold,
perCharThreshold: perCharThreshold,
ignoreEntropy: ignoreEntropy,
Expand Down