Skip to content

Commit 58e4fcc

Browse files
Dimitar Banchevccojocar
authored andcommitted
Split the G401 rule into two separate ones
Now the G401 rule is split into hashing and encryption algorithms. G401 is responsible for checking the usage of MD5 and SHA1, with corresponding CWE of 328. And G405(New rule) is responsible for checking the usege of DES and RC4, with corresponding CWE of 327.
1 parent 2e71f37 commit 58e4fcc

File tree

11 files changed

+480
-14
lines changed

11 files changed

+480
-14
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,10 +151,11 @@ directory you can supply `./...` as the input argument.
151151
- G305: File traversal when extracting zip/tar archive
152152
- G306: Poor file permissions used when writing to a new file
153153
- G307: Poor file permissions used when creating a file with os.Create
154-
- G401: Detect the usage of DES, RC4, MD5 or SHA1
154+
- G401: Detect the usage of MD5 or SHA1
155155
- G402: Look for bad TLS connection settings
156156
- G403: Ensure minimum RSA key length of 2048 bits
157157
- G404: Insecure random number source (rand)
158+
- G405: Detect the usage of DES or RC4
158159
- G501: Import blocklist: crypto/md5
159160
- G502: Import blocklist: crypto/des
160161
- G503: Import blocklist: crypto/rc4

analyzer_test.go

Lines changed: 307 additions & 0 deletions
Large diffs are not rendered by default.

call_list_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,32 @@ var _ = Describe("Call List", func() {
9494
Expect(matched).Should(Equal(1))
9595
})
9696

97+
It("should match a package call expression", func() {
98+
// Create file to be scanned
99+
pkg := testutils.NewTestPackage()
100+
defer pkg.Close()
101+
pkg.AddFile("cipher.go", testutils.SampleCodeG405[0].Code[0])
102+
103+
ctx := pkg.CreateContext("cipher.go")
104+
105+
// Search for des.NewCipher()
106+
calls.Add("crypto/des", "NewCipher")
107+
108+
// Stub out visitor and count number of matched call expr
109+
matched := 0
110+
v := testutils.NewMockVisitor()
111+
v.Context = ctx
112+
v.Callback = func(n ast.Node, ctx *gosec.Context) bool {
113+
if _, ok := n.(*ast.CallExpr); ok && calls.ContainsPkgCallExpr(n, ctx, false) != nil {
114+
matched++
115+
}
116+
return true
117+
}
118+
ast.Walk(v, ctx.Root)
119+
Expect(matched).Should(Equal(1))
120+
})
121+
122+
97123
It("should match a call expression", func() {
98124
// Create file to be scanned
99125
pkg := testutils.NewTestPackage()

issue/issue.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ var ruleToCWE = map[string]string{
8282
"G402": "295",
8383
"G403": "310",
8484
"G404": "338",
85+
"G405": "327",
8586
"G501": "327",
8687
"G502": "327",
8788
"G503": "327",

report/formatter_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -281,8 +281,8 @@ var _ = Describe("Formatter", func() {
281281
"G101", "G102", "G103", "G104", "G106", "G107", "G109",
282282
"G110", "G111", "G112", "G113", "G201", "G202", "G203",
283283
"G204", "G301", "G302", "G303", "G304", "G305", "G401",
284-
"G402", "G403", "G404", "G501", "G502", "G503", "G504",
285-
"G505", "G601",
284+
"G402", "G403", "G404", "G405", "G501", "G502", "G503",
285+
"G504", "G505", "G601",
286286
}
287287

288288
It("csv formatted report should contain the CWE mapping", func() {

rules/rulelist.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,11 @@ func Generate(trackSuppressions bool, filters ...RuleFilter) RuleList {
9494
{"G307", "Poor file permissions used when creating a file with os.Create", NewOsCreatePerms},
9595

9696
// crypto
97-
{"G401", "Detect the usage of DES, RC4, MD5 or SHA1", NewUsesWeakCryptography},
97+
{"G401", "Detect the usage of MD5 or SHA1", NewUsesWeakCryptographyHash},
9898
{"G402", "Look for bad TLS connection settings", NewIntermediateTLSCheck},
9999
{"G403", "Ensure minimum RSA key length of 2048 bits", NewWeakKeyStrength},
100100
{"G404", "Insecure random number source (rand)", NewWeakRandCheck},
101+
{"G405", "Detect the usage of DES or RC4", NewUsesWeakCryptographyEncryption},
101102

102103
// blocklist
103104
{"G501", "Import blocklist: crypto/md5", NewBlocklistedImportMD5},

rules/rules_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,14 @@ var _ = Describe("gosec rules", func() {
175175
runner("G404", testutils.SampleCodeG404)
176176
})
177177

178+
It("should detect weak crypto algorithms", func() {
179+
runner("G405", testutils.SampleCodeG405)
180+
})
181+
182+
It("should detect weak crypto algorithms", func() {
183+
runner("G405", testutils.SampleCodeG405b)
184+
})
185+
178186
It("should detect blocklisted imports - MD5", func() {
179187
runner("G501", testutils.SampleCodeG501)
180188
})

rules/weakcrypto.go renamed to rules/weakcryptoencryption.go

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,16 @@ import (
2121
"github.com/securego/gosec/v2/issue"
2222
)
2323

24-
type usesWeakCryptography struct {
24+
type usesWeakCryptographyEncryption struct {
2525
issue.MetaData
2626
blocklist map[string][]string
2727
}
2828

29-
func (r *usesWeakCryptography) ID() string {
29+
func (r *usesWeakCryptographyEncryption) ID() string {
3030
return r.MetaData.ID
3131
}
3232

33-
func (r *usesWeakCryptography) Match(n ast.Node, c *gosec.Context) (*issue.Issue, error) {
33+
func (r *usesWeakCryptographyEncryption) Match(n ast.Node, c *gosec.Context) (*issue.Issue, error) {
3434
for pkg, funcs := range r.blocklist {
3535
if _, matched := gosec.MatchCallByPackage(n, c, pkg, funcs...); matched {
3636
return c.NewIssue(n, r.ID(), r.What, r.Severity, r.Confidence), nil
@@ -39,14 +39,12 @@ func (r *usesWeakCryptography) Match(n ast.Node, c *gosec.Context) (*issue.Issue
3939
return nil, nil
4040
}
4141

42-
// NewUsesWeakCryptography detects uses of des.* md5.* or rc4.*
43-
func NewUsesWeakCryptography(id string, _ gosec.Config) (gosec.Rule, []ast.Node) {
42+
// NewUsesWeakCryptographyEncryption detects uses of des.*, rc4.*
43+
func NewUsesWeakCryptographyEncryption(id string, _ gosec.Config) (gosec.Rule, []ast.Node) {
4444
calls := make(map[string][]string)
4545
calls["crypto/des"] = []string{"NewCipher", "NewTripleDESCipher"}
46-
calls["crypto/md5"] = []string{"New", "Sum"}
47-
calls["crypto/sha1"] = []string{"New", "Sum"}
4846
calls["crypto/rc4"] = []string{"NewCipher"}
49-
rule := &usesWeakCryptography{
47+
rule := &usesWeakCryptographyEncryption{
5048
blocklist: calls,
5149
MetaData: issue.MetaData{
5250
ID: id,

rules/weakcryptohash.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// (c) Copyright 2016 Hewlett Packard Enterprise Development LP
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package rules
16+
17+
import (
18+
"go/ast"
19+
20+
"github.com/securego/gosec/v2"
21+
"github.com/securego/gosec/v2/issue"
22+
)
23+
24+
type usesWeakCryptographyHash struct {
25+
issue.MetaData
26+
blocklist map[string][]string
27+
}
28+
29+
func (r *usesWeakCryptographyHash) ID() string {
30+
return r.MetaData.ID
31+
}
32+
33+
func (r *usesWeakCryptographyHash) Match(n ast.Node, c *gosec.Context) (*issue.Issue, error) {
34+
for pkg, funcs := range r.blocklist {
35+
if _, matched := gosec.MatchCallByPackage(n, c, pkg, funcs...); matched {
36+
return c.NewIssue(n, r.ID(), r.What, r.Severity, r.Confidence), nil
37+
}
38+
}
39+
return nil, nil
40+
}
41+
42+
// NewUsesWeakCryptographyHash detects uses of md5.*, sha1.*
43+
func NewUsesWeakCryptographyHash(id string, _ gosec.Config) (gosec.Rule, []ast.Node) {
44+
calls := make(map[string][]string)
45+
calls["crypto/md5"] = []string{"New", "Sum"}
46+
calls["crypto/sha1"] = []string{"New", "Sum"}
47+
rule := &usesWeakCryptographyHash{
48+
blocklist: calls,
49+
MetaData: issue.MetaData{
50+
ID: id,
51+
Severity: issue.Medium,
52+
Confidence: issue.High,
53+
What: "Use of weak cryptographic primitive",
54+
},
55+
}
56+
return rule, []ast.Node{(*ast.CallExpr)(nil)}
57+
}

testutils/g401_samples.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package testutils
33
import "github.com/securego/gosec/v2"
44

55
var (
6-
// SampleCodeG401 - Use of weak crypto MD5
6+
// SampleCodeG401 - Use of weak crypto hash MD5
77
SampleCodeG401 = []CodeSample{
88
{[]string{`
99
package main
@@ -39,7 +39,7 @@ func main() {
3939
`}, 1, gosec.NewConfig()},
4040
}
4141

42-
// SampleCodeG401b - Use of weak crypto SHA1
42+
// SampleCodeG401b - Use of weak crypto hash SHA1
4343
SampleCodeG401b = []CodeSample{
4444
{[]string{`
4545
package main

testutils/g405_samples .go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package testutils
2+
3+
import "github.com/securego/gosec/v2"
4+
5+
var (
6+
// SampleCodeG405 - Use of weak crypto encryption DES
7+
SampleCodeG405 = []CodeSample{
8+
{[]string{`
9+
package main
10+
11+
import (
12+
"crypto/des"
13+
"fmt"
14+
)
15+
16+
func main() {
17+
// Weakness: Usage of weak encryption algorithm
18+
19+
c, e := des.NewCipher([]byte("mySecret"))
20+
21+
if e != nil {
22+
panic("We have a problem: " + e.Error())
23+
}
24+
25+
data := []byte("hello world")
26+
fmt.Println("Plain", string(data))
27+
c.Encrypt(data, data)
28+
29+
fmt.Println("Encrypted", string(data))
30+
c.Decrypt(data, data)
31+
32+
fmt.Println("Plain Decrypted", string(data))
33+
}
34+
35+
`}, 1, gosec.NewConfig()},
36+
}
37+
38+
// SampleCodeG405b - Use of weak crypto encryption RC4
39+
SampleCodeG405b = []CodeSample{
40+
{[]string{`
41+
package main
42+
43+
import (
44+
"crypto/rc4"
45+
"fmt"
46+
)
47+
48+
func main() {
49+
// Weakness: Usage of weak encryption algorithm
50+
51+
c, _ := rc4.NewCipher([]byte("mySecret"))
52+
53+
data := []byte("hello world")
54+
fmt.Println("Plain", string(data))
55+
c.XORKeyStream(data, data)
56+
57+
cryptCipher2, _ := rc4.NewCipher([]byte("mySecret"))
58+
59+
fmt.Println("Encrypted", string(data))
60+
cryptCipher2.XORKeyStream(data, data)
61+
62+
fmt.Println("Plain Decrypted", string(data))
63+
}
64+
65+
`}, 1, gosec.NewConfig()},
66+
}
67+
)

0 commit comments

Comments
 (0)