mirror of
https://github.com/securego/gosec.git
synced 2024-11-05 11:35:51 +00:00
Added more rules
* Rule G406 responsible for the usage of deprecated MD4 and RIPEMD160 added. * Rules G506, G507 responsible for tracking the usage of the already mentioned libraries added. * Slight changes in the Makefile(`make clean` wasn't removing all expected files) * Added license to `analyzer_test.go`
This commit is contained in:
parent
6382394ce8
commit
9a4a741e6b
13 changed files with 536 additions and 3 deletions
2
Makefile
2
Makefile
|
@ -68,7 +68,7 @@ build-race:
|
|||
go build -race -o $(BIN) ./cmd/gosec/
|
||||
|
||||
clean:
|
||||
rm -rf build vendor dist coverage.txt
|
||||
rm -rf build vendor dist coverage.out
|
||||
rm -f release image $(BIN)
|
||||
|
||||
release:
|
||||
|
|
|
@ -156,11 +156,14 @@ directory you can supply `./...` as the input argument.
|
|||
- G403: Ensure minimum RSA key length of 2048 bits
|
||||
- G404: Insecure random number source (rand)
|
||||
- G405: Detect the usage of DES or RC4
|
||||
- G406: Detect the usage of MD4 or RIPEMD160
|
||||
- G501: Import blocklist: crypto/md5
|
||||
- G502: Import blocklist: crypto/des
|
||||
- G503: Import blocklist: crypto/rc4
|
||||
- G504: Import blocklist: net/http/cgi
|
||||
- G505: Import blocklist: crypto/sha1
|
||||
- G506: Import blocklist: golang.org/x/crypto/md4
|
||||
- G507: Import blocklist: golang.org/x/crypto/ripemd160
|
||||
- G601: Implicit memory aliasing of items from a range statement (only for Go 1.21 or lower)
|
||||
- G602: Slice access out of bounds
|
||||
|
||||
|
|
321
analyzer_test.go
321
analyzer_test.go
|
@ -1,3 +1,17 @@
|
|||
// (c) Copyright 2024 Mercedes-Benz Tech Innovation GmbH
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package gosec_test
|
||||
|
||||
import (
|
||||
|
@ -156,6 +170,22 @@ var _ = Describe("Analyzer", func() {
|
|||
Expect(controlIssues).Should(HaveLen(sample.Errors))
|
||||
})
|
||||
|
||||
It("should find errors when nosec is not in use", func() {
|
||||
sample := testutils.SampleCodeG406[0]
|
||||
source := sample.Code[0]
|
||||
analyzer.LoadRules(rules.Generate(false, rules.NewRuleFilter(false, "G406")).RulesInfo())
|
||||
|
||||
controlPackage := testutils.NewTestPackage()
|
||||
defer controlPackage.Close()
|
||||
controlPackage.AddFile("md4.go", source)
|
||||
err := controlPackage.Build()
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
err = analyzer.Process(buildTags, controlPackage.Path)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
controlIssues, _, _ := analyzer.Report()
|
||||
Expect(controlIssues).Should(HaveLen(sample.Errors))
|
||||
})
|
||||
|
||||
It("should report Go build errors and invalid files", func() {
|
||||
analyzer.LoadRules(rules.Generate(false).RulesInfo())
|
||||
pkg := testutils.NewTestPackage()
|
||||
|
@ -218,6 +248,23 @@ var _ = Describe("Analyzer", func() {
|
|||
Expect(nosecIssues).Should(BeEmpty())
|
||||
})
|
||||
|
||||
It("should not report errors when a nosec line comment is present", func() {
|
||||
sample := testutils.SampleCodeG406[0]
|
||||
source := sample.Code[0]
|
||||
analyzer.LoadRules(rules.Generate(false, rules.NewRuleFilter(false, "G406")).RulesInfo())
|
||||
|
||||
nosecPackage := testutils.NewTestPackage()
|
||||
defer nosecPackage.Close()
|
||||
nosecSource := strings.Replace(source, "h := md4.New()", "h := md4.New() //#nosec", 1)
|
||||
nosecPackage.AddFile("md4.go", nosecSource)
|
||||
err := nosecPackage.Build()
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
err = analyzer.Process(buildTags, nosecPackage.Path)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
nosecIssues, _, _ := analyzer.Report()
|
||||
Expect(nosecIssues).Should(BeEmpty())
|
||||
})
|
||||
|
||||
It("should not report errors when a nosec block comment is present", func() {
|
||||
sample := testutils.SampleCodeG401[0]
|
||||
source := sample.Code[0]
|
||||
|
@ -252,6 +299,23 @@ var _ = Describe("Analyzer", func() {
|
|||
Expect(nosecIssues).Should(BeEmpty())
|
||||
})
|
||||
|
||||
It("should not report errors when a nosec block comment is present", func() {
|
||||
sample := testutils.SampleCodeG406[0]
|
||||
source := sample.Code[0]
|
||||
analyzer.LoadRules(rules.Generate(false, rules.NewRuleFilter(false, "G406")).RulesInfo())
|
||||
|
||||
nosecPackage := testutils.NewTestPackage()
|
||||
defer nosecPackage.Close()
|
||||
nosecSource := strings.Replace(source, "h := md4.New()", "h := md4.New() /* #nosec */", 1)
|
||||
nosecPackage.AddFile("md4.go", nosecSource)
|
||||
err := nosecPackage.Build()
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
err = analyzer.Process(buildTags, nosecPackage.Path)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
nosecIssues, _, _ := analyzer.Report()
|
||||
Expect(nosecIssues).Should(BeEmpty())
|
||||
})
|
||||
|
||||
It("should not report errors when an exclude comment is present for the correct rule", func() {
|
||||
// Rule for MD5 weak crypto usage
|
||||
sample := testutils.SampleCodeG401[0]
|
||||
|
@ -288,6 +352,24 @@ var _ = Describe("Analyzer", func() {
|
|||
Expect(nosecIssues).Should(BeEmpty())
|
||||
})
|
||||
|
||||
It("should not report errors when an exclude comment is present for the correct rule", func() {
|
||||
// Rule for MD4 deprecated weak crypto usage
|
||||
sample := testutils.SampleCodeG406[0]
|
||||
source := sample.Code[0]
|
||||
analyzer.LoadRules(rules.Generate(false, rules.NewRuleFilter(false, "G406")).RulesInfo())
|
||||
|
||||
nosecPackage := testutils.NewTestPackage()
|
||||
defer nosecPackage.Close()
|
||||
nosecSource := strings.Replace(source, "h := md4.New()", "h := md4.New() //#nosec G406", 1)
|
||||
nosecPackage.AddFile("md4.go", nosecSource)
|
||||
err := nosecPackage.Build()
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
err = analyzer.Process(buildTags, nosecPackage.Path)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
nosecIssues, _, _ := analyzer.Report()
|
||||
Expect(nosecIssues).Should(BeEmpty())
|
||||
})
|
||||
|
||||
It("should not report errors when a nosec block and line comment are present", func() {
|
||||
sample := testutils.SampleCodeG101[23]
|
||||
source := sample.Code[0]
|
||||
|
@ -368,6 +450,23 @@ var _ = Describe("Analyzer", func() {
|
|||
Expect(nosecIssues).Should(HaveLen(sample.Errors))
|
||||
})
|
||||
|
||||
It("should report errors when an exclude comment is present for a different rule", func() {
|
||||
sample := testutils.SampleCodeG406[0]
|
||||
source := sample.Code[0]
|
||||
analyzer.LoadRules(rules.Generate(false, rules.NewRuleFilter(false, "G406")).RulesInfo())
|
||||
|
||||
nosecPackage := testutils.NewTestPackage()
|
||||
defer nosecPackage.Close()
|
||||
nosecSource := strings.Replace(source, "h := md4.New()", "h := md4.New() //#nosec G301", 1)
|
||||
nosecPackage.AddFile("md4.go", nosecSource)
|
||||
err := nosecPackage.Build()
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
err = analyzer.Process(buildTags, nosecPackage.Path)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
nosecIssues, _, _ := analyzer.Report()
|
||||
Expect(nosecIssues).Should(HaveLen(sample.Errors))
|
||||
})
|
||||
|
||||
It("should not report errors when an exclude comment is present for multiple rules, including the correct rule", func() {
|
||||
sample := testutils.SampleCodeG401[0]
|
||||
source := sample.Code[0]
|
||||
|
@ -406,6 +505,25 @@ var _ = Describe("Analyzer", func() {
|
|||
Expect(nosecIssues).Should(BeEmpty())
|
||||
})
|
||||
|
||||
It("should not report errors when an exclude comment is present for multiple rules, including the correct rule", func() {
|
||||
sample := testutils.SampleCodeG406[0]
|
||||
source := sample.Code[0]
|
||||
analyzer.LoadRules(rules.Generate(false, rules.NewRuleFilter(false, "G406")).RulesInfo())
|
||||
|
||||
nosecPackage := testutils.NewTestPackage()
|
||||
defer nosecPackage.Close()
|
||||
nosecSource := strings.Replace(source, "h := md4.New()", "h := md4.New() //#nosec G301 G406", 1)
|
||||
nosecPackage.AddFile("md4.go", nosecSource)
|
||||
err := nosecPackage.Build()
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
err = analyzer.Process(buildTags, nosecPackage.Path)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
err = analyzer.Process(buildTags, nosecPackage.Path)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
nosecIssues, _, _ := analyzer.Report()
|
||||
Expect(nosecIssues).Should(BeEmpty())
|
||||
})
|
||||
|
||||
It("should pass the build tags", func() {
|
||||
sample := testutils.SampleCodeBuildTag[0]
|
||||
source := sample.Code[0]
|
||||
|
@ -479,6 +597,29 @@ var _ = Describe("Analyzer", func() {
|
|||
Expect(nosecIssues).Should(HaveLen(sample.Errors))
|
||||
})
|
||||
|
||||
It("should be possible to overwrite nosec comments, and report issues", func() {
|
||||
// Rule for MD4 weak crypto usage
|
||||
sample := testutils.SampleCodeG406[0]
|
||||
source := sample.Code[0]
|
||||
|
||||
// overwrite nosec option
|
||||
nosecIgnoreConfig := gosec.NewConfig()
|
||||
nosecIgnoreConfig.SetGlobal(gosec.Nosec, "true")
|
||||
customAnalyzer := gosec.NewAnalyzer(nosecIgnoreConfig, tests, false, false, 1, logger)
|
||||
customAnalyzer.LoadRules(rules.Generate(false, rules.NewRuleFilter(false, "G406")).RulesInfo())
|
||||
|
||||
nosecPackage := testutils.NewTestPackage()
|
||||
defer nosecPackage.Close()
|
||||
nosecSource := strings.Replace(source, "h := md4.New()", "h := md4.New() //#nosec", 1)
|
||||
nosecPackage.AddFile("md4.go", nosecSource)
|
||||
err := nosecPackage.Build()
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
err = customAnalyzer.Process(buildTags, nosecPackage.Path)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
nosecIssues, _, _ := customAnalyzer.Report()
|
||||
Expect(nosecIssues).Should(HaveLen(sample.Errors))
|
||||
})
|
||||
|
||||
It("should be possible to overwrite nosec comments, and report issues but they should not be counted", func() {
|
||||
// Rule for MD5 weak crypto usage
|
||||
sample := testutils.SampleCodeG401[0]
|
||||
|
@ -531,6 +672,32 @@ var _ = Describe("Analyzer", func() {
|
|||
Expect(metrics.NumNosec).Should(Equal(1))
|
||||
})
|
||||
|
||||
It("should be possible to overwrite nosec comments, and report issues but they should not be counted", func() {
|
||||
// Rule for MD4 weak crypto usage
|
||||
sample := testutils.SampleCodeG406[0]
|
||||
source := sample.Code[0]
|
||||
|
||||
// overwrite nosec option
|
||||
nosecIgnoreConfig := gosec.NewConfig()
|
||||
nosecIgnoreConfig.SetGlobal(gosec.Nosec, "mynosec")
|
||||
nosecIgnoreConfig.SetGlobal(gosec.ShowIgnored, "true")
|
||||
customAnalyzer := gosec.NewAnalyzer(nosecIgnoreConfig, tests, false, false, 1, logger)
|
||||
customAnalyzer.LoadRules(rules.Generate(false, rules.NewRuleFilter(false, "G406")).RulesInfo())
|
||||
|
||||
nosecPackage := testutils.NewTestPackage()
|
||||
defer nosecPackage.Close()
|
||||
nosecSource := strings.Replace(source, "h := md4.New()", "h := md4.New() // #mynosec", 1)
|
||||
nosecPackage.AddFile("md4.go", nosecSource)
|
||||
err := nosecPackage.Build()
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
err = customAnalyzer.Process(buildTags, nosecPackage.Path)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
nosecIssues, metrics, _ := customAnalyzer.Report()
|
||||
Expect(nosecIssues).Should(HaveLen(sample.Errors))
|
||||
Expect(metrics.NumFound).Should(Equal(0))
|
||||
Expect(metrics.NumNosec).Should(Equal(1))
|
||||
})
|
||||
|
||||
It("should not report errors when nosec tag is in front of a line", func() {
|
||||
sample := testutils.SampleCodeG401[0]
|
||||
source := sample.Code[0]
|
||||
|
@ -565,6 +732,23 @@ var _ = Describe("Analyzer", func() {
|
|||
Expect(nosecIssues).Should(BeEmpty())
|
||||
})
|
||||
|
||||
It("should not report errors when nosec tag is in front of a line", func() {
|
||||
sample := testutils.SampleCodeG406[0]
|
||||
source := sample.Code[0]
|
||||
analyzer.LoadRules(rules.Generate(false, rules.NewRuleFilter(false, "G406")).RulesInfo())
|
||||
|
||||
nosecPackage := testutils.NewTestPackage()
|
||||
defer nosecPackage.Close()
|
||||
nosecSource := strings.Replace(source, "h := md4.New()", "//Some description\n//#nosec G406\nh := md4.New()", 1)
|
||||
nosecPackage.AddFile("md4.go", nosecSource)
|
||||
err := nosecPackage.Build()
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
err = analyzer.Process(buildTags, nosecPackage.Path)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
nosecIssues, _, _ := analyzer.Report()
|
||||
Expect(nosecIssues).Should(BeEmpty())
|
||||
})
|
||||
|
||||
It("should report errors when nosec tag is not in front of a line", func() {
|
||||
sample := testutils.SampleCodeG401[0]
|
||||
source := sample.Code[0]
|
||||
|
@ -599,6 +783,23 @@ var _ = Describe("Analyzer", func() {
|
|||
Expect(nosecIssues).Should(HaveLen(sample.Errors))
|
||||
})
|
||||
|
||||
It("should report errors when nosec tag is not in front of a line", func() {
|
||||
sample := testutils.SampleCodeG406[0]
|
||||
source := sample.Code[0]
|
||||
analyzer.LoadRules(rules.Generate(false, rules.NewRuleFilter(false, "G406")).RulesInfo())
|
||||
|
||||
nosecPackage := testutils.NewTestPackage()
|
||||
defer nosecPackage.Close()
|
||||
nosecSource := strings.Replace(source, "h := md4.New()", "//Some description\n//Another description #nosec G406\nh := md4.New()", 1)
|
||||
nosecPackage.AddFile("md4.go", nosecSource)
|
||||
err := nosecPackage.Build()
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
err = analyzer.Process(buildTags, nosecPackage.Path)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
nosecIssues, _, _ := analyzer.Report()
|
||||
Expect(nosecIssues).Should(HaveLen(sample.Errors))
|
||||
})
|
||||
|
||||
It("should not report errors when rules are in front of nosec tag even rules are wrong", func() {
|
||||
sample := testutils.SampleCodeG401[0]
|
||||
source := sample.Code[0]
|
||||
|
@ -633,6 +834,23 @@ var _ = Describe("Analyzer", func() {
|
|||
Expect(nosecIssues).Should(BeEmpty())
|
||||
})
|
||||
|
||||
It("should not report errors when rules are in front of nosec tag even rules are wrong", func() {
|
||||
sample := testutils.SampleCodeG406[0]
|
||||
source := sample.Code[0]
|
||||
analyzer.LoadRules(rules.Generate(false, rules.NewRuleFilter(false, "G406")).RulesInfo())
|
||||
|
||||
nosecPackage := testutils.NewTestPackage()
|
||||
defer nosecPackage.Close()
|
||||
nosecSource := strings.Replace(source, "h := md4.New()", "//G301\n//#nosec\nh := md4.New()", 1)
|
||||
nosecPackage.AddFile("md4.go", nosecSource)
|
||||
err := nosecPackage.Build()
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
err = analyzer.Process(buildTags, nosecPackage.Path)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
nosecIssues, _, _ := analyzer.Report()
|
||||
Expect(nosecIssues).Should(BeEmpty())
|
||||
})
|
||||
|
||||
It("should report errors when there are nosec tags after a #nosec WrongRuleList annotation", func() {
|
||||
sample := testutils.SampleCodeG401[0]
|
||||
source := sample.Code[0]
|
||||
|
@ -667,6 +885,23 @@ var _ = Describe("Analyzer", func() {
|
|||
Expect(nosecIssues).Should(HaveLen(sample.Errors))
|
||||
})
|
||||
|
||||
It("should report errors when there are nosec tags after a #nosec WrongRuleList annotation", func() {
|
||||
sample := testutils.SampleCodeG406[0]
|
||||
source := sample.Code[0]
|
||||
analyzer.LoadRules(rules.Generate(false, rules.NewRuleFilter(false, "G406")).RulesInfo())
|
||||
|
||||
nosecPackage := testutils.NewTestPackage()
|
||||
defer nosecPackage.Close()
|
||||
nosecSource := strings.Replace(source, "h := md4.New()", "//#nosec\n//G301\n//#nosec\nh := md4.New()", 1)
|
||||
nosecPackage.AddFile("md4.go", nosecSource)
|
||||
err := nosecPackage.Build()
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
err = analyzer.Process(buildTags, nosecPackage.Path)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
nosecIssues, _, _ := analyzer.Report()
|
||||
Expect(nosecIssues).Should(HaveLen(sample.Errors))
|
||||
})
|
||||
|
||||
It("should be possible to use an alternative nosec tag", func() {
|
||||
// Rule for MD5 weak crypto usage
|
||||
sample := testutils.SampleCodeG401[0]
|
||||
|
@ -713,6 +948,29 @@ var _ = Describe("Analyzer", func() {
|
|||
Expect(nosecIssues).Should(BeEmpty())
|
||||
})
|
||||
|
||||
It("should be possible to use an alternative nosec tag", func() {
|
||||
// Rule for MD4 deprecated weak crypto usage
|
||||
sample := testutils.SampleCodeG406[0]
|
||||
source := sample.Code[0]
|
||||
|
||||
// overwrite nosec option
|
||||
nosecIgnoreConfig := gosec.NewConfig()
|
||||
nosecIgnoreConfig.SetGlobal(gosec.NoSecAlternative, "falsePositive")
|
||||
customAnalyzer := gosec.NewAnalyzer(nosecIgnoreConfig, tests, false, false, 1, logger)
|
||||
customAnalyzer.LoadRules(rules.Generate(false, rules.NewRuleFilter(false, "G406")).RulesInfo())
|
||||
|
||||
nosecPackage := testutils.NewTestPackage()
|
||||
defer nosecPackage.Close()
|
||||
nosecSource := strings.Replace(source, "h := md4.New()", "h := md4.New() // #falsePositive", 1)
|
||||
nosecPackage.AddFile("md4.go", nosecSource)
|
||||
err := nosecPackage.Build()
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
err = customAnalyzer.Process(buildTags, nosecPackage.Path)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
nosecIssues, _, _ := customAnalyzer.Report()
|
||||
Expect(nosecIssues).Should(BeEmpty())
|
||||
})
|
||||
|
||||
It("should ignore vulnerabilities when the default tag is found", func() {
|
||||
// Rule for MD5 weak crypto usage
|
||||
sample := testutils.SampleCodeG401[0]
|
||||
|
@ -759,6 +1017,29 @@ var _ = Describe("Analyzer", func() {
|
|||
Expect(nosecIssues).Should(BeEmpty())
|
||||
})
|
||||
|
||||
It("should ignore vulnerabilities when the default tag is found", func() {
|
||||
// Rule for MD4 deprecated weak crypto usage
|
||||
sample := testutils.SampleCodeG406[0]
|
||||
source := sample.Code[0]
|
||||
|
||||
// overwrite nosec option
|
||||
nosecIgnoreConfig := gosec.NewConfig()
|
||||
nosecIgnoreConfig.SetGlobal(gosec.NoSecAlternative, "falsePositive")
|
||||
customAnalyzer := gosec.NewAnalyzer(nosecIgnoreConfig, tests, false, false, 1, logger)
|
||||
customAnalyzer.LoadRules(rules.Generate(false, rules.NewRuleFilter(false, "G406")).RulesInfo())
|
||||
|
||||
nosecPackage := testutils.NewTestPackage()
|
||||
defer nosecPackage.Close()
|
||||
nosecSource := strings.Replace(source, "h := md4.New()", "h := md4.New() //#nosec", 1)
|
||||
nosecPackage.AddFile("md4.go", nosecSource)
|
||||
err := nosecPackage.Build()
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
err = customAnalyzer.Process(buildTags, nosecPackage.Path)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
nosecIssues, _, _ := customAnalyzer.Report()
|
||||
Expect(nosecIssues).Should(BeEmpty())
|
||||
})
|
||||
|
||||
It("should be able to analyze Go test package", func() {
|
||||
customAnalyzer := gosec.NewAnalyzer(nil, true, false, false, 1, logger)
|
||||
customAnalyzer.LoadRules(rules.Generate(false).RulesInfo())
|
||||
|
@ -1100,6 +1381,26 @@ var _ = Describe("Analyzer", func() {
|
|||
Expect(issues[0].Suppressions[0].Justification).To(Equal("Justification"))
|
||||
})
|
||||
|
||||
It("should not report an error if the violation is suppressed", func() {
|
||||
sample := testutils.SampleCodeG406[0]
|
||||
source := sample.Code[0]
|
||||
analyzer.LoadRules(rules.Generate(false, rules.NewRuleFilter(false, "G406")).RulesInfo())
|
||||
|
||||
nosecPackage := testutils.NewTestPackage()
|
||||
defer nosecPackage.Close()
|
||||
nosecSource := strings.Replace(source, "h := md4.New()", "h := md4.New() //#nosec G406 -- Justification", 1)
|
||||
nosecPackage.AddFile("md4.go", nosecSource)
|
||||
err := nosecPackage.Build()
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
err = analyzer.Process(buildTags, nosecPackage.Path)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
issues, _, _ := analyzer.Report()
|
||||
Expect(issues).To(HaveLen(sample.Errors))
|
||||
Expect(issues[0].Suppressions).To(HaveLen(1))
|
||||
Expect(issues[0].Suppressions[0].Kind).To(Equal("inSource"))
|
||||
Expect(issues[0].Suppressions[0].Justification).To(Equal("Justification"))
|
||||
})
|
||||
|
||||
It("should not report an error if the violation is suppressed without certain rules", func() {
|
||||
sample := testutils.SampleCodeG401[0]
|
||||
source := sample.Code[0]
|
||||
|
@ -1140,6 +1441,26 @@ var _ = Describe("Analyzer", func() {
|
|||
Expect(issues[0].Suppressions[0].Justification).To(Equal(""))
|
||||
})
|
||||
|
||||
It("should not report an error if the violation is suppressed without certain rules", func() {
|
||||
sample := testutils.SampleCodeG406[0]
|
||||
source := sample.Code[0]
|
||||
analyzer.LoadRules(rules.Generate(false, rules.NewRuleFilter(false, "G406")).RulesInfo())
|
||||
|
||||
nosecPackage := testutils.NewTestPackage()
|
||||
defer nosecPackage.Close()
|
||||
nosecSource := strings.Replace(source, "h := md4.New()", "h := md4.New() //#nosec", 1)
|
||||
nosecPackage.AddFile("md4.go", nosecSource)
|
||||
err := nosecPackage.Build()
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
err = analyzer.Process(buildTags, nosecPackage.Path)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
issues, _, _ := analyzer.Report()
|
||||
Expect(issues).To(HaveLen(sample.Errors))
|
||||
Expect(issues[0].Suppressions).To(HaveLen(1))
|
||||
Expect(issues[0].Suppressions[0].Kind).To(Equal("inSource"))
|
||||
Expect(issues[0].Suppressions[0].Justification).To(Equal(""))
|
||||
})
|
||||
|
||||
It("should not report an error if the rule is not included", func() {
|
||||
sample := testutils.SampleCodeG101[0]
|
||||
source := sample.Code[0]
|
||||
|
|
|
@ -119,6 +119,31 @@ var _ = Describe("Call List", func() {
|
|||
Expect(matched).Should(Equal(1))
|
||||
})
|
||||
|
||||
It("should match a package call expression", func() {
|
||||
// Create file to be scanned
|
||||
pkg := testutils.NewTestPackage()
|
||||
defer pkg.Close()
|
||||
pkg.AddFile("md4.go", testutils.SampleCodeG406[0].Code[0])
|
||||
|
||||
ctx := pkg.CreateContext("md4.go")
|
||||
|
||||
// Search for md4.New()
|
||||
calls.Add("golang.org/x/crypto/md4", "New")
|
||||
|
||||
// Stub out visitor and count number of matched call expr
|
||||
matched := 0
|
||||
v := testutils.NewMockVisitor()
|
||||
v.Context = ctx
|
||||
v.Callback = func(n ast.Node, ctx *gosec.Context) bool {
|
||||
if _, ok := n.(*ast.CallExpr); ok && calls.ContainsPkgCallExpr(n, ctx, false) != nil {
|
||||
matched++
|
||||
}
|
||||
return true
|
||||
}
|
||||
ast.Walk(v, ctx.Root)
|
||||
Expect(matched).Should(Equal(1))
|
||||
})
|
||||
|
||||
It("should match a call expression", func() {
|
||||
// Create file to be scanned
|
||||
pkg := testutils.NewTestPackage()
|
||||
|
|
|
@ -83,11 +83,14 @@ var ruleToCWE = map[string]string{
|
|||
"G403": "310",
|
||||
"G404": "338",
|
||||
"G405": "327",
|
||||
"G406": "328",
|
||||
"G501": "327",
|
||||
"G502": "327",
|
||||
"G503": "327",
|
||||
"G504": "327",
|
||||
"G505": "327",
|
||||
"G506": "327",
|
||||
"G507": "327",
|
||||
"G601": "118",
|
||||
"G602": "118",
|
||||
}
|
||||
|
|
|
@ -281,8 +281,8 @@ var _ = Describe("Formatter", func() {
|
|||
"G101", "G102", "G103", "G104", "G106", "G107", "G109",
|
||||
"G110", "G111", "G112", "G113", "G201", "G202", "G203",
|
||||
"G204", "G301", "G302", "G303", "G304", "G305", "G401",
|
||||
"G402", "G403", "G404", "G405", "G501", "G502", "G503",
|
||||
"G504", "G505", "G601",
|
||||
"G402", "G403", "G404", "G405", "G406", "G501", "G502",
|
||||
"G503", "G504", "G505", "G506", "G507", "G601",
|
||||
}
|
||||
|
||||
It("csv formatted report should contain the CWE mapping", func() {
|
||||
|
|
|
@ -93,3 +93,17 @@ func NewBlocklistedImportSHA1(id string, conf gosec.Config) (gosec.Rule, []ast.N
|
|||
"crypto/sha1": "Blocklisted import crypto/sha1: weak cryptographic primitive",
|
||||
})
|
||||
}
|
||||
|
||||
// NewBlocklistedImportMD4 fails if MD4 is imported
|
||||
func NewBlocklistedImportMD4(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
return NewBlocklistedImports(id, conf, map[string]string{
|
||||
"golang.org/x/crypto/md4": "Blocklisted import golang.org/x/crypto/md4: deprecated and weak cryptographic primitive",
|
||||
})
|
||||
}
|
||||
|
||||
// NewBlocklistedImportRIPEMD160 fails if RIPEMD160 is imported
|
||||
func NewBlocklistedImportRIPEMD160(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
return NewBlocklistedImports(id, conf, map[string]string{
|
||||
"golang.org/x/crypto/ripemd160": "Blocklisted import golang.org/x/crypto/ripemd160: deprecated and weak cryptographic primitive",
|
||||
})
|
||||
}
|
||||
|
|
|
@ -99,6 +99,7 @@ func Generate(trackSuppressions bool, filters ...RuleFilter) RuleList {
|
|||
{"G403", "Ensure minimum RSA key length of 2048 bits", NewWeakKeyStrength},
|
||||
{"G404", "Insecure random number source (rand)", NewWeakRandCheck},
|
||||
{"G405", "Detect the usage of DES or RC4", NewUsesWeakCryptographyEncryption},
|
||||
{"G406", "Detect the usage of deprecated MD4 or RIPEMD160", NewUsesWeakDeprecatedCryptographyHash},
|
||||
|
||||
// blocklist
|
||||
{"G501", "Import blocklist: crypto/md5", NewBlocklistedImportMD5},
|
||||
|
@ -106,6 +107,8 @@ func Generate(trackSuppressions bool, filters ...RuleFilter) RuleList {
|
|||
{"G503", "Import blocklist: crypto/rc4", NewBlocklistedImportRC4},
|
||||
{"G504", "Import blocklist: net/http/cgi", NewBlocklistedImportCGI},
|
||||
{"G505", "Import blocklist: crypto/sha1", NewBlocklistedImportSHA1},
|
||||
{"G506", "Import blocklist: golang.org/x/crypto/md4", NewBlocklistedImportMD4},
|
||||
{"G507", "Import blocklist: golang.org/x/crypto/ripemd160", NewBlocklistedImportRIPEMD160},
|
||||
|
||||
// memory safety
|
||||
{"G601", "Implicit memory aliasing in RangeStmt", NewImplicitAliasing},
|
||||
|
|
|
@ -183,6 +183,14 @@ var _ = Describe("gosec rules", func() {
|
|||
runner("G405", testutils.SampleCodeG405b)
|
||||
})
|
||||
|
||||
It("should detect weak crypto algorithms", func() {
|
||||
runner("G406", testutils.SampleCodeG406)
|
||||
})
|
||||
|
||||
It("should detect weak crypto algorithms", func() {
|
||||
runner("G406", testutils.SampleCodeG406b)
|
||||
})
|
||||
|
||||
It("should detect blocklisted imports - MD5", func() {
|
||||
runner("G501", testutils.SampleCodeG501)
|
||||
})
|
||||
|
@ -203,6 +211,14 @@ var _ = Describe("gosec rules", func() {
|
|||
runner("G505", testutils.SampleCodeG505)
|
||||
})
|
||||
|
||||
It("should detect blocklisted imports - MD4", func() {
|
||||
runner("G506", testutils.SampleCodeG506)
|
||||
})
|
||||
|
||||
It("should detect blocklisted imports - RIPEMD160", func() {
|
||||
runner("G507", testutils.SampleCodeG507)
|
||||
})
|
||||
|
||||
It("should detect implicit aliasing in ForRange", func() {
|
||||
major, minor, _ := gosec.GoVersion()
|
||||
if major <= 1 && minor < 22 {
|
||||
|
|
57
rules/weakdepricatedcryptohash.go
Normal file
57
rules/weakdepricatedcryptohash.go
Normal file
|
@ -0,0 +1,57 @@
|
|||
// (c) Copyright 2024 Mercedes-Benz Tech Innovation GmbH
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package rules
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
|
||||
"github.com/securego/gosec/v2"
|
||||
"github.com/securego/gosec/v2/issue"
|
||||
)
|
||||
|
||||
type usesWeakDeprecatedCryptographyHash struct {
|
||||
issue.MetaData
|
||||
blocklist map[string][]string
|
||||
}
|
||||
|
||||
func (r *usesWeakDeprecatedCryptographyHash) ID() string {
|
||||
return r.MetaData.ID
|
||||
}
|
||||
|
||||
func (r *usesWeakDeprecatedCryptographyHash) Match(n ast.Node, c *gosec.Context) (*issue.Issue, error) {
|
||||
for pkg, funcs := range r.blocklist {
|
||||
if _, matched := gosec.MatchCallByPackage(n, c, pkg, funcs...); matched {
|
||||
return c.NewIssue(n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// NewUsesWeakCryptographyHash detects uses of md4.New, ripemd160.New
|
||||
func NewUsesWeakDeprecatedCryptographyHash(id string, _ gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
calls := make(map[string][]string)
|
||||
calls["golang.org/x/crypto/md4"] = []string{"New"}
|
||||
calls["golang.org/x/crypto/ripemd160"] = []string{"New"}
|
||||
rule := &usesWeakDeprecatedCryptographyHash{
|
||||
blocklist: calls,
|
||||
MetaData: issue.MetaData{
|
||||
ID: id,
|
||||
Severity: issue.Medium,
|
||||
Confidence: issue.High,
|
||||
What: "Use of deprecated weak cryptographic primitive",
|
||||
},
|
||||
}
|
||||
return rule, []ast.Node{(*ast.CallExpr)(nil)}
|
||||
}
|
45
testutils/g406_samples.go
Normal file
45
testutils/g406_samples.go
Normal file
|
@ -0,0 +1,45 @@
|
|||
package testutils
|
||||
|
||||
import "github.com/securego/gosec/v2"
|
||||
|
||||
var (
|
||||
// SampleCodeG406 - Use of deprecated weak crypto hash MD4
|
||||
SampleCodeG406 = []CodeSample{
|
||||
{[]string{`
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/crypto/md4"
|
||||
)
|
||||
|
||||
func main() {
|
||||
h := md4.New()
|
||||
h.Write([]byte("test"))
|
||||
fmt.Println(hex.EncodeToString(h.Sum(nil)))
|
||||
}
|
||||
`}, 1, gosec.NewConfig()},
|
||||
}
|
||||
|
||||
// SampleCodeG406b - Use of deprecated weak crypto hash RIPEMD160
|
||||
SampleCodeG406b = []CodeSample{
|
||||
{[]string{`
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/crypto/ripemd160"
|
||||
)
|
||||
|
||||
func main() {
|
||||
h := ripemd160.New()
|
||||
h.Write([]byte("test"))
|
||||
fmt.Println(hex.EncodeToString(h.Sum(nil)))
|
||||
}
|
||||
`}, 1, gosec.NewConfig()},
|
||||
}
|
||||
)
|
23
testutils/g506_samples.go
Normal file
23
testutils/g506_samples.go
Normal file
|
@ -0,0 +1,23 @@
|
|||
package testutils
|
||||
|
||||
import "github.com/securego/gosec/v2"
|
||||
|
||||
// SampleCodeG506 - Blocklisted import MD4
|
||||
var SampleCodeG506 = []CodeSample{
|
||||
{[]string{`
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/crypto/md4"
|
||||
)
|
||||
|
||||
func main() {
|
||||
h := md4.New()
|
||||
h.Write([]byte("test"))
|
||||
fmt.Println(hex.EncodeToString(h.Sum(nil)))
|
||||
}
|
||||
`}, 1, gosec.NewConfig()},
|
||||
}
|
23
testutils/g507_samples.go
Normal file
23
testutils/g507_samples.go
Normal file
|
@ -0,0 +1,23 @@
|
|||
package testutils
|
||||
|
||||
import "github.com/securego/gosec/v2"
|
||||
|
||||
// SampleCodeG507 - Blocklisted import RIPEMD160
|
||||
var SampleCodeG507 = []CodeSample{
|
||||
{[]string{`
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/crypto/ripemd160"
|
||||
)
|
||||
|
||||
func main() {
|
||||
h := ripemd160.New()
|
||||
h.Write([]byte("test"))
|
||||
fmt.Println(hex.EncodeToString(h.Sum(nil)))
|
||||
}
|
||||
`}, 1, gosec.NewConfig()},
|
||||
}
|
Loading…
Reference in a new issue