diff --git a/helpers.go b/helpers.go index abe4c15..bc01a94 100644 --- a/helpers.go +++ b/helpers.go @@ -256,3 +256,28 @@ func GetPkgAbsPath(pkgPath string) (string, error) { } return absPath, nil } + +// ConcatString recusively concatenates strings from a binary expression +func ConcatString(n *ast.BinaryExpr) (string, bool) { + var s string + // sub expressions are found in X object, Y object is always last BasicLit + if rightOperand, ok := n.Y.(*ast.BasicLit); ok { + if str, err := GetString(rightOperand); err == nil { + s = str + s + } + } else { + return "", false + } + if leftOperand, ok := n.X.(*ast.BinaryExpr); ok { + if recursion, ok := ConcatString(leftOperand); ok { + s = recursion + s + } + } else if leftOperand, ok := n.X.(*ast.BasicLit); ok { + if str, err := GetString(leftOperand); err == nil { + s = str + s + } + } else { + return "", false + } + return s, true +} diff --git a/rules/sql.go b/rules/sql.go index 655f4b0..fe7732d 100644 --- a/rules/sql.go +++ b/rules/sql.go @@ -106,6 +106,16 @@ func (s *sqlStrFormat) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) // TODO(gm) improve confidence if database/sql is being used if node := s.calls.ContainsCallExpr(n, c); node != nil { + // concats callexpr arg strings together if needed before regex evaluation + if argExpr, ok := node.Args[0].(*ast.BinaryExpr); ok { + if fullStr, ok := gosec.ConcatString(argExpr); ok { + if s.MatchPatterns(fullStr) { + return gosec.NewIssue(c, n, s.ID(), s.What, s.Severity, s.Confidence), + nil + } + } + } + if arg, e := gosec.GetString(node.Args[0]); s.MatchPatterns(arg) && e == nil { return gosec.NewIssue(c, n, s.ID(), s.What, s.Severity, s.Confidence), nil }