Tim Heckman 60fd647987
Update gosec linter to v2; add .test files to .gitignore (#1062)
This change updates the `gosec` linter to its v2 version. It seems like v2
maintained API compatibility for the functionality we use, so we only needed to
update the dependency and imports.

Please note, this does not use a tagged version of `gosec` and instead is the
latest `master` commit due to this issue: https://github.com/securego/gosec/issues/470.
Once this issue is resolved we should update `gosec` to a tagged release.

This also adds a line to the `.gitignore` file, to ignore the `.test` output
files that get generated by `go test`. This could accidentally get left behind,
so no use committing binary files.

Fixes #1052
2020-05-03 14:05:00 +03:00

98 lines
2.4 KiB
Go

package golinters
import (
"fmt"
"go/token"
"io/ioutil"
"log"
"strconv"
"sync"
"github.com/securego/gosec/v2"
"github.com/securego/gosec/v2/rules"
"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/packages"
"github.com/golangci/golangci-lint/pkg/golinters/goanalysis"
"github.com/golangci/golangci-lint/pkg/lint/linter"
"github.com/golangci/golangci-lint/pkg/result"
)
const gosecName = "gosec"
func NewGosec() *goanalysis.Linter {
var mu sync.Mutex
var resIssues []goanalysis.Issue
gasConfig := gosec.NewConfig()
enabledRules := rules.Generate()
logger := log.New(ioutil.Discard, "", 0)
analyzer := &analysis.Analyzer{
Name: gosecName,
Doc: goanalysis.TheOnlyanalyzerDoc,
}
return goanalysis.NewLinter(
gosecName,
"Inspects source code for security problems",
[]*analysis.Analyzer{analyzer},
nil,
).WithContextSetter(func(lintCtx *linter.Context) {
analyzer.Run = func(pass *analysis.Pass) (interface{}, error) {
gosecAnalyzer := gosec.NewAnalyzer(gasConfig, true, logger)
gosecAnalyzer.LoadRules(enabledRules.Builders())
pkg := &packages.Package{
Fset: pass.Fset,
Syntax: pass.Files,
Types: pass.Pkg,
TypesInfo: pass.TypesInfo,
}
gosecAnalyzer.Check(pkg)
issues, _, _ := gosecAnalyzer.Report()
if len(issues) == 0 {
return nil, nil
}
res := make([]goanalysis.Issue, 0, len(issues))
for _, i := range issues {
text := fmt.Sprintf("%s: %s", i.RuleID, i.What) // TODO: use severity and confidence
var r *result.Range
line, err := strconv.Atoi(i.Line)
if err != nil {
r = &result.Range{}
if n, rerr := fmt.Sscanf(i.Line, "%d-%d", &r.From, &r.To); rerr != nil || n != 2 {
lintCtx.Log.Warnf("Can't convert gosec line number %q of %v to int: %s", i.Line, i, err)
continue
}
line = r.From
}
column, err := strconv.Atoi(i.Col)
if err != nil {
lintCtx.Log.Warnf("Can't convert gosec column number %q of %v to int: %s", i.Col, i, err)
continue
}
res = append(res, goanalysis.NewIssue(&result.Issue{
Pos: token.Position{
Filename: i.File,
Line: line,
Column: column,
},
Text: text,
LineRange: r,
FromLinter: gosecName,
}, pass))
}
mu.Lock()
resIssues = append(resIssues, res...)
mu.Unlock()
return nil, nil
}
}).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue {
return resIssues
}).WithLoadMode(goanalysis.LoadModeTypesInfo)
}