Skip to content

Commit

Permalink
gosec: convert global settings as map with proper key type (#3779)
Browse files Browse the repository at this point in the history
Co-authored-by: Fernandez Ludovic <ldez@users.noreply.github.com>
  • Loading branch information
bcho and ldez committed Apr 21, 2023
1 parent 745ecb9 commit 52edd01
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 11 deletions.
44 changes: 33 additions & 11 deletions pkg/golinters/gosec.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
}
70 changes: 70 additions & 0 deletions pkg/golinters/gosec_test.go
Original file line number Diff line number Diff line change
@@ -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)
})
}
}
5 changes: 5 additions & 0 deletions test/testdata/configs/gosec_global_option.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
linters-settings:
gosec:
config:
global:
nosec: true
14 changes: 14 additions & 0 deletions test/testdata/gosec_global_option.go
Original file line number Diff line number Diff line change
@@ -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)
}

0 comments on commit 52edd01

Please sign in to comment.