From b3942b410f0e38ef4301266370b9868501bb7128 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Fabianski?= Date: Mon, 19 Feb 2024 17:37:47 +0100 Subject: [PATCH] fix(golang): handle sprintf properly (#1503) --- .../golang/detectors/string/string.go | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/internal/languages/golang/detectors/string/string.go b/internal/languages/golang/detectors/string/string.go index 01c85bc3d..f04857450 100644 --- a/internal/languages/golang/detectors/string/string.go +++ b/internal/languages/golang/detectors/string/string.go @@ -1,6 +1,9 @@ package string import ( + "fmt" + "regexp" + "github.com/bearer/bearer/internal/scanner/ast/query" "github.com/bearer/bearer/internal/scanner/ast/tree" "github.com/bearer/bearer/internal/scanner/ruleset" @@ -10,6 +13,11 @@ import ( "github.com/bearer/bearer/internal/scanner/detectors/types" ) +var ( + simpleInterpolationRegexp = regexp.MustCompile(`%#?[a-zA-Z]`) + numericInterpolationRegexp = regexp.MustCompile(`%\d?\.?\d?f`) +) + type stringDetector struct { types.DetectorBase } @@ -27,6 +35,50 @@ func (detector *stringDetector) DetectAt( detectorContext types.Context, ) ([]interface{}, error) { switch node.Type() { + case "call_expression": + function := node.ChildByFieldName("function") + if function.Type() == "selector_expression" { + field := function.ChildByFieldName("field") + if field.Type() == "field_identifier" && field.Content() == "Sprintf" { + arguments := node.ChildByFieldName("arguments").NamedChildren() + + stringValue, isLiteral, err := common.GetStringValue(arguments[0], detectorContext) + if err != nil || !isLiteral { + return nil, err + } + + stringValue = simpleInterpolationRegexp.ReplaceAllString(stringValue, "%s") // %s %d %#v %t + stringValue = numericInterpolationRegexp.ReplaceAllString(stringValue, "%s") // %2.2f %.2f %2f %2.f + + newArguments := []any{} + for index, argument := range arguments { + if index == 0 { + continue + } + + childValue, childIsLiteral, err := common.GetStringValue(argument, detectorContext) + if err != nil { + return nil, err + } + + if !childIsLiteral { + isLiteral = false + if childValue == "" { + childValue = common.NonLiteralValue + } + } + + newArguments = append(newArguments, childValue) + } + + value := fmt.Sprintf(stringValue, newArguments...) + + return []interface{}{common.String{ + Value: value, + IsLiteral: isLiteral, + }}, nil + } + } case "binary_expression": if node.Children()[1].Content() == "+" { return common.ConcatenateChildStrings(node, detectorContext)