Skip to content

Commit 52edd01

Browse files
bcholdez
andauthored
gosec: convert global settings as map with proper key type (#3779)
Co-authored-by: Fernandez Ludovic <[email protected]>
1 parent 745ecb9 commit 52edd01

File tree

4 files changed

+122
-11
lines changed

4 files changed

+122
-11
lines changed

pkg/golinters/gosec.go

+33-11
Original file line numberDiff line numberDiff line change
@@ -26,20 +26,11 @@ func NewGosec(settings *config.GoSecSettings) *goanalysis.Linter {
2626
var mu sync.Mutex
2727
var resIssues []goanalysis.Issue
2828

29-
conf := gosec.NewConfig()
30-
3129
var filters []rules.RuleFilter
30+
conf := gosec.NewConfig()
3231
if settings != nil {
3332
filters = gosecRuleFilters(settings.Includes, settings.Excludes)
34-
35-
for k, v := range settings.Config {
36-
if k != gosec.Globals {
37-
// Uses ToUpper because the parsing of the map's key change the key to lowercase.
38-
// The value is not impacted by that: the case is respected.
39-
k = strings.ToUpper(k)
40-
}
41-
conf.Set(k, v)
42-
}
33+
conf = toGosecConfig(settings)
4334
}
4435

4536
logger := log.New(io.Discard, "", 0)
@@ -140,6 +131,35 @@ func runGoSec(lintCtx *linter.Context, pass *analysis.Pass, settings *config.GoS
140131
return issues
141132
}
142133

134+
func toGosecConfig(settings *config.GoSecSettings) gosec.Config {
135+
conf := gosec.NewConfig()
136+
137+
for k, v := range settings.Config {
138+
if k == gosec.Globals {
139+
convertGosecGlobals(v, conf)
140+
continue
141+
}
142+
143+
// Uses ToUpper because the parsing of the map's key change the key to lowercase.
144+
// The value is not impacted by that: the case is respected.
145+
conf.Set(strings.ToUpper(k), v)
146+
}
147+
148+
return conf
149+
}
150+
151+
// based on https://github.com/securego/gosec/blob/47bfd4eb6fc7395940933388550b547538b4c946/config.go#L52-L62
152+
func convertGosecGlobals(globalOptionFromConfig any, conf gosec.Config) {
153+
globalOptionMap, ok := globalOptionFromConfig.(map[string]any)
154+
if !ok {
155+
return
156+
}
157+
158+
for k, v := range globalOptionMap {
159+
conf.SetGlobal(gosec.GlobalOption(k), fmt.Sprintf("%v", v))
160+
}
161+
}
162+
143163
// based on https://github.com/securego/gosec/blob/569328eade2ccbad4ce2d0f21ee158ab5356a5cf/cmd/gosec/main.go#L170-L188
144164
func gosecRuleFilters(includes, excludes []string) []rules.RuleFilter {
145165
var filters []rules.RuleFilter
@@ -173,10 +193,12 @@ func convertToScore(str string) (gosec.Score, error) {
173193
// code borrowed from https://github.com/securego/gosec/blob/69213955dacfd560562e780f723486ef1ca6d486/cmd/gosec/main.go#L264-L276
174194
func filterIssues(issues []*gosec.Issue, severity, confidence gosec.Score) []*gosec.Issue {
175195
res := make([]*gosec.Issue, 0)
196+
176197
for _, issue := range issues {
177198
if issue.Severity >= severity && issue.Confidence >= confidence {
178199
res = append(res, issue)
179200
}
180201
}
202+
181203
return res
182204
}

pkg/golinters/gosec_test.go

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package golinters
2+
3+
import (
4+
"testing"
5+
6+
"github.com/securego/gosec/v2"
7+
"github.com/stretchr/testify/assert"
8+
9+
"github.com/golangci/golangci-lint/pkg/config"
10+
)
11+
12+
func Test_toGosecConfig(t *testing.T) {
13+
testCases := []struct {
14+
desc string
15+
settings *config.GoSecSettings
16+
expected gosec.Config
17+
}{
18+
{
19+
desc: "empty config map",
20+
settings: &config.GoSecSettings{},
21+
expected: gosec.Config{
22+
"global": map[gosec.GlobalOption]string{},
23+
},
24+
},
25+
{
26+
desc: "with global settings",
27+
settings: &config.GoSecSettings{
28+
Config: map[string]any{
29+
gosec.Globals: map[string]any{
30+
string(gosec.Nosec): true,
31+
string(gosec.Audit): "true",
32+
},
33+
},
34+
},
35+
expected: gosec.Config{
36+
"global": map[gosec.GlobalOption]string{
37+
"audit": "true",
38+
"nosec": "true",
39+
},
40+
},
41+
},
42+
{
43+
desc: "rule specified setting",
44+
settings: &config.GoSecSettings{
45+
Config: map[string]any{
46+
"g101": map[string]any{
47+
"pattern": "(?i)example",
48+
},
49+
"G301": "0750",
50+
},
51+
},
52+
expected: gosec.Config{
53+
"G101": map[string]any{"pattern": "(?i)example"},
54+
"G301": "0750",
55+
"global": map[gosec.GlobalOption]string{},
56+
},
57+
},
58+
}
59+
60+
for _, test := range testCases {
61+
test := test
62+
t.Run(test.desc, func(t *testing.T) {
63+
t.Parallel()
64+
65+
conf := toGosecConfig(test.settings)
66+
67+
assert.Equal(t, test.expected, conf)
68+
})
69+
}
70+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
linters-settings:
2+
gosec:
3+
config:
4+
global:
5+
nosec: true

test/testdata/gosec_global_option.go

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//golangcitest:args -Egosec
2+
//golangcitest:config_path testdata/configs/gosec_global_option.yml
3+
package testdata
4+
5+
import (
6+
"crypto/md5" // want "G501: Blocklisted import crypto/md5: weak cryptographic primitive"
7+
"log"
8+
)
9+
10+
func Gosec() {
11+
// #nosec G401
12+
h := md5.New() // want "G401: Use of weak cryptographic primitive"
13+
log.Print(h)
14+
}

0 commit comments

Comments
 (0)