gosec: convert global settings as map with proper key type (#3779)

Co-authored-by: Fernandez Ludovic <ldez@users.noreply.github.com>
This commit is contained in:
hbc 2023-04-22 04:20:59 +08:00 committed by GitHub
parent 745ecb9efe
commit 52edd01248
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 122 additions and 11 deletions

View File

@ -26,20 +26,11 @@ func NewGosec(settings *config.GoSecSettings) *goanalysis.Linter {
var mu sync.Mutex
var resIssues []goanalysis.Issue
conf := gosec.NewConfig()
var filters []rules.RuleFilter
conf := gosec.NewConfig()
if settings != nil {
filters = gosecRuleFilters(settings.Includes, settings.Excludes)
for k, v := range settings.Config {
if k != gosec.Globals {
// Uses ToUpper because the parsing of the map's key change the key to lowercase.
// The value is not impacted by that: the case is respected.
k = strings.ToUpper(k)
}
conf.Set(k, v)
}
conf = toGosecConfig(settings)
}
logger := log.New(io.Discard, "", 0)
@ -140,6 +131,35 @@ func runGoSec(lintCtx *linter.Context, pass *analysis.Pass, settings *config.GoS
return issues
}
func toGosecConfig(settings *config.GoSecSettings) gosec.Config {
conf := gosec.NewConfig()
for k, v := range settings.Config {
if k == gosec.Globals {
convertGosecGlobals(v, conf)
continue
}
// Uses ToUpper because the parsing of the map's key change the key to lowercase.
// The value is not impacted by that: the case is respected.
conf.Set(strings.ToUpper(k), v)
}
return conf
}
// based on https://github.com/securego/gosec/blob/47bfd4eb6fc7395940933388550b547538b4c946/config.go#L52-L62
func convertGosecGlobals(globalOptionFromConfig any, conf gosec.Config) {
globalOptionMap, ok := globalOptionFromConfig.(map[string]any)
if !ok {
return
}
for k, v := range globalOptionMap {
conf.SetGlobal(gosec.GlobalOption(k), fmt.Sprintf("%v", v))
}
}
// based on https://github.com/securego/gosec/blob/569328eade2ccbad4ce2d0f21ee158ab5356a5cf/cmd/gosec/main.go#L170-L188
func gosecRuleFilters(includes, excludes []string) []rules.RuleFilter {
var filters []rules.RuleFilter
@ -173,10 +193,12 @@ func convertToScore(str string) (gosec.Score, error) {
// code borrowed from https://github.com/securego/gosec/blob/69213955dacfd560562e780f723486ef1ca6d486/cmd/gosec/main.go#L264-L276
func filterIssues(issues []*gosec.Issue, severity, confidence gosec.Score) []*gosec.Issue {
res := make([]*gosec.Issue, 0)
for _, issue := range issues {
if issue.Severity >= severity && issue.Confidence >= confidence {
res = append(res, issue)
}
}
return res
}

View File

@ -0,0 +1,70 @@
package golinters
import (
"testing"
"github.com/securego/gosec/v2"
"github.com/stretchr/testify/assert"
"github.com/golangci/golangci-lint/pkg/config"
)
func Test_toGosecConfig(t *testing.T) {
testCases := []struct {
desc string
settings *config.GoSecSettings
expected gosec.Config
}{
{
desc: "empty config map",
settings: &config.GoSecSettings{},
expected: gosec.Config{
"global": map[gosec.GlobalOption]string{},
},
},
{
desc: "with global settings",
settings: &config.GoSecSettings{
Config: map[string]any{
gosec.Globals: map[string]any{
string(gosec.Nosec): true,
string(gosec.Audit): "true",
},
},
},
expected: gosec.Config{
"global": map[gosec.GlobalOption]string{
"audit": "true",
"nosec": "true",
},
},
},
{
desc: "rule specified setting",
settings: &config.GoSecSettings{
Config: map[string]any{
"g101": map[string]any{
"pattern": "(?i)example",
},
"G301": "0750",
},
},
expected: gosec.Config{
"G101": map[string]any{"pattern": "(?i)example"},
"G301": "0750",
"global": map[gosec.GlobalOption]string{},
},
},
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
conf := toGosecConfig(test.settings)
assert.Equal(t, test.expected, conf)
})
}
}

View File

@ -0,0 +1,5 @@
linters-settings:
gosec:
config:
global:
nosec: true

14
test/testdata/gosec_global_option.go vendored Normal file
View File

@ -0,0 +1,14 @@
//golangcitest:args -Egosec
//golangcitest:config_path testdata/configs/gosec_global_option.yml
package testdata
import (
"crypto/md5" // want "G501: Blocklisted import crypto/md5: weak cryptographic primitive"
"log"
)
func Gosec() {
// #nosec G401
h := md5.New() // want "G401: Use of weak cryptographic primitive"
log.Print(h)
}