Skip to content

Commit 7851918

Browse files
ccojocargcmurphy
authored andcommitted
Add support to exclude arbitrary folders from scanning (#353)
Signed-off-by: Cosmin Cojocar <[email protected]>
1 parent 1c35be8 commit 7851918

File tree

4 files changed

+79
-15
lines changed

4 files changed

+79
-15
lines changed

README.md

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -137,13 +137,21 @@ of functions which will be skipped when auditing the not checked errors:
137137
gosec will fetch automatically the dependencies of the code which is being analyzed when go modules are turned on (e.g.` GO111MODULE=on`). If this is not the case,
138138
the dependencies need to be explicitly downloaded by running the `go get -d` command before the scan.
139139

140+
### Excluding test files and folders
140141

141-
### Excluding files
142+
gosec will ignore test files across all packages and any dependencies in your vendor directory.
142143

143-
gosec will ignore tests files and any dependencies in your vendor directory. The scanning of these artifacts can be enabled with the following flags:
144+
The scanning of test files can be enabled with the following flag:
144145

145146
```bash
146-
gosec -tests -vendor ./...
147+
148+
gosec -tests ./...
149+
```
150+
151+
Also additional folders can be excluded as follows:
152+
153+
```bash
154+
gosec -exclude-dir=rules -exclude-dir=cmd ./...
147155
```
148156

149157
### Annotating code

cmd/gosec/main.go

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import (
2020
"io/ioutil"
2121
"log"
2222
"os"
23-
"regexp"
2423
"sort"
2524
"strings"
2625

@@ -58,6 +57,17 @@ USAGE:
5857
`
5958
)
6059

60+
type arrayFlags []string
61+
62+
func (a *arrayFlags) String() string {
63+
return strings.Join(*a, " ")
64+
}
65+
66+
func (a *arrayFlags) Set(value string) error {
67+
*a = append(*a, value)
68+
return nil
69+
}
70+
6171
var (
6272
// #nosec flag
6373
flagIgnoreNoSec = flag.Bool("nosec", false, "Ignores #nosec comments when set")
@@ -92,9 +102,6 @@ var (
92102
// go build tags
93103
flagBuildTags = flag.String("tags", "", "Comma separated list of build tags")
94104

95-
// scan the vendor folder
96-
flagScanVendor = flag.Bool("vendor", false, "Scan the vendor folder")
97-
98105
// fail by severity
99106
flagSeverity = flag.String("severity", "low", "Filter out the issues with a lower severity than the given value. Valid options are: low, medium, high")
100107

@@ -110,6 +117,9 @@ var (
110117
// print version and quit with exit code 0
111118
flagVersion = flag.Bool("version", false, "Print version and quit with exit code 0")
112119

120+
// exlude the folders from scan
121+
flagDirsExclude arrayFlags
122+
113123
logger *log.Logger
114124
)
115125

@@ -233,6 +243,13 @@ func main() {
233243
// Setup usage description
234244
flag.Usage = usage
235245

246+
// Setup the excluded folders from scan
247+
flag.Var(&flagDirsExclude, "exclude-dir", "Exclude folder from scan (can be specified multiple times)")
248+
err := flag.Set("exclude-dir", "vendor")
249+
if err != nil {
250+
fmt.Fprintf(os.Stderr, "\nError: failed to exclude the %q directory from scan", "vendor")
251+
}
252+
236253
// Parse command line arguments
237254
flag.Parse()
238255

@@ -291,13 +308,10 @@ func main() {
291308
analyzer := gosec.NewAnalyzer(config, *flagScanTests, logger)
292309
analyzer.LoadRules(ruleDefinitions.Builders())
293310

294-
var vendor *regexp.Regexp
295-
if !*flagScanVendor {
296-
vendor = regexp.MustCompile(`([\\/])?vendor([\\/])?`)
297-
}
311+
excludedDirs := gosec.ExcludedDirsRegExp(flagDirsExclude)
298312
var packages []string
299313
for _, path := range flag.Args() {
300-
pcks, err := gosec.PackagePaths(path, vendor)
314+
pcks, err := gosec.PackagePaths(path, excludedDirs)
301315
if err != nil {
302316
logger.Fatal(err)
303317
}

helpers.go

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ func FindVarIdentities(n *ast.BinaryExpr, c *Context) ([]*ast.Ident, bool) {
360360
}
361361

362362
// PackagePaths returns a slice with all packages path at given root directory
363-
func PackagePaths(root string, exclude *regexp.Regexp) ([]string, error) {
363+
func PackagePaths(root string, excludes []*regexp.Regexp) ([]string, error) {
364364
if strings.HasSuffix(root, "...") {
365365
root = root[0 : len(root)-3]
366366
} else {
@@ -370,7 +370,7 @@ func PackagePaths(root string, exclude *regexp.Regexp) ([]string, error) {
370370
err := filepath.Walk(root, func(path string, f os.FileInfo, err error) error {
371371
if filepath.Ext(path) == ".go" {
372372
path = filepath.Dir(path)
373-
if exclude != nil && exclude.MatchString(path) {
373+
if isExcluded(path, excludes) {
374374
return nil
375375
}
376376
paths[path] = true
@@ -388,6 +388,30 @@ func PackagePaths(root string, exclude *regexp.Regexp) ([]string, error) {
388388
return result, nil
389389
}
390390

391+
// isExcluded checks if a string matches any of the exclusion regexps
392+
func isExcluded(str string, excludes []*regexp.Regexp) bool {
393+
if excludes == nil {
394+
return false
395+
}
396+
for _, exclude := range excludes {
397+
if exclude != nil && exclude.MatchString(str) {
398+
return true
399+
}
400+
}
401+
return false
402+
}
403+
404+
// ExcludedDirsRegExp builds the regexps for a list of excluded dirs provided as strings
405+
func ExcludedDirsRegExp(excludedDirs []string) []*regexp.Regexp {
406+
var exps []*regexp.Regexp
407+
for _, excludedDir := range excludedDirs {
408+
str := fmt.Sprintf(`([\\/])?%s([\\/])?`, excludedDir)
409+
r := regexp.MustCompile(str)
410+
exps = append(exps, r)
411+
}
412+
return exps
413+
}
414+
391415
// RootPath returns the absolute root path of a scan
392416
func RootPath(root string) (string, error) {
393417
if strings.HasSuffix(root, "...") {

helpers_test.go

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ var _ = Describe("Helpers", func() {
4343
Expect(err).ShouldNot(HaveOccurred())
4444
exclude, err := regexp.Compile(`([\\/])?vendor([\\/])?`)
4545
Expect(err).ShouldNot(HaveOccurred())
46-
paths, err := gosec.PackagePaths(dir+"/...", exclude)
46+
paths, err := gosec.PackagePaths(dir+"/...", []*regexp.Regexp{exclude})
4747
Expect(err).ShouldNot(HaveOccurred())
4848
Expect(paths).Should(Equal([]string{dir}))
4949
})
@@ -73,4 +73,22 @@ var _ = Describe("Helpers", func() {
7373
Expect(root).Should(Equal(filepath.Join(cwd, base)))
7474
})
7575
})
76+
77+
Context("when excluding the dirs", func() {
78+
It("should create a proper regexp", func() {
79+
r := gosec.ExcludedDirsRegExp([]string{"test"})
80+
Expect(len(r)).Should(Equal(1))
81+
match := r[0].MatchString("/home/go/src/project/test/pkg")
82+
Expect(match).Should(BeTrue())
83+
match = r[0].MatchString("/home/go/src/project/vendor/pkg")
84+
Expect(match).Should(BeFalse())
85+
})
86+
87+
It("should create no regexp when dir list is empty", func() {
88+
r := gosec.ExcludedDirsRegExp(nil)
89+
Expect(len(r)).Should(Equal(0))
90+
r = gosec.ExcludedDirsRegExp([]string{})
91+
Expect(len(r)).Should(Equal(0))
92+
})
93+
})
7694
})

0 commit comments

Comments
 (0)