
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
98 lines
2.4 KiB
Go
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)
|
|
}
|