Fix lint and fail on error in the ci build

This commit is contained in:
Matthieu MOREL 2021-05-31 10:44:12 +02:00 committed by GitHub
parent dbb9811e62
commit 1256f16f33
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
51 changed files with 218 additions and 203 deletions

View file

@ -20,7 +20,6 @@ jobs:
${{ runner.os }}-go- ${{ runner.os }}-go-
- name: golangci-lint - name: golangci-lint
uses: golangci/golangci-lint-action@v2 uses: golangci/golangci-lint-action@v2
continue-on-error: true
with: with:
version: latest version: latest
test: test:

View file

@ -1,13 +1,23 @@
linters: linters:
enable: enable:
- megacheck - asciicheck
- govet - bodyclose
- unparam
- unconvert
- misspell
- gofmt
- golint
- gosec
- nakedret
- dogsled
- depguard - depguard
- dogsled
- durationcheck
- errcheck
- exportloopref
- gofmt
- gofumpt
- goimports
- gosec
- govet
- importas
- megacheck
- misspell
- nakedret
- nolintlint
- revive
- unconvert
- unparam
- wastedassign

View file

@ -28,7 +28,6 @@ import (
"reflect" "reflect"
"regexp" "regexp"
"strconv" "strconv"
"strings" "strings"
"golang.org/x/tools/go/packages" "golang.org/x/tools/go/packages"

View file

@ -17,7 +17,6 @@ import (
) )
var _ = Describe("Analyzer", func() { var _ = Describe("Analyzer", func() {
var ( var (
analyzer *gosec.Analyzer analyzer *gosec.Analyzer
logger *log.Logger logger *log.Logger
@ -30,7 +29,6 @@ var _ = Describe("Analyzer", func() {
}) })
Context("when processing a package", func() { Context("when processing a package", func() {
It("should not report an error if the package contains no Go files", func() { It("should not report an error if the package contains no Go files", func() {
analyzer.LoadRules(rules.Generate().Builders()) analyzer.LoadRules(rules.Generate().Builders())
dir, err := ioutil.TempDir("", "empty") dir, err := ioutil.TempDir("", "empty")
@ -118,7 +116,6 @@ var _ = Describe("Analyzer", func() {
Expect(err).ShouldNot(HaveOccurred()) Expect(err).ShouldNot(HaveOccurred())
controlIssues, _, _ := analyzer.Report() controlIssues, _, _ := analyzer.Report()
Expect(controlIssues).Should(HaveLen(sample.Errors)) Expect(controlIssues).Should(HaveLen(sample.Errors))
}) })
It("should report Go build errors and invalid files", func() { It("should report Go build errors and invalid files", func() {
@ -262,7 +259,6 @@ var _ = Describe("Analyzer", func() {
Expect(err).ShouldNot(HaveOccurred()) Expect(err).ShouldNot(HaveOccurred())
nosecIssues, _, _ := customAnalyzer.Report() nosecIssues, _, _ := customAnalyzer.Report()
Expect(nosecIssues).Should(HaveLen(sample.Errors)) Expect(nosecIssues).Should(HaveLen(sample.Errors))
}) })
It("should be possible to use an alternative nosec tag", func() { It("should be possible to use an alternative nosec tag", func() {
@ -286,7 +282,6 @@ var _ = Describe("Analyzer", func() {
Expect(err).ShouldNot(HaveOccurred()) Expect(err).ShouldNot(HaveOccurred())
nosecIssues, _, _ := customAnalyzer.Report() nosecIssues, _, _ := customAnalyzer.Report()
Expect(nosecIssues).Should(HaveLen(0)) Expect(nosecIssues).Should(HaveLen(0))
}) })
It("should ignore vulnerabilities when the default tag is found", func() { It("should ignore vulnerabilities when the default tag is found", func() {
@ -310,7 +305,6 @@ var _ = Describe("Analyzer", func() {
Expect(err).ShouldNot(HaveOccurred()) Expect(err).ShouldNot(HaveOccurred())
nosecIssues, _, _ := customAnalyzer.Report() nosecIssues, _, _ := customAnalyzer.Report()
Expect(nosecIssues).Should(HaveLen(0)) Expect(nosecIssues).Should(HaveLen(0))
}) })
It("should be able to analyze Go test package", func() { It("should be able to analyze Go test package", func() {
@ -356,7 +350,6 @@ var _ = Describe("Analyzer", func() {
}) })
Context("when parsing errors from a package", func() { Context("when parsing errors from a package", func() {
It("should return no error when the error list is empty", func() { It("should return no error when the error list is empty", func() {
pkg := &packages.Package{} pkg := &packages.Package{}
err := analyzer.ParseErrors(pkg) err := analyzer.ParseErrors(pkg)

View file

@ -10,9 +10,7 @@ import (
) )
var _ = Describe("Call List", func() { var _ = Describe("Call List", func() {
var ( var calls gosec.CallList
calls gosec.CallList
)
BeforeEach(func() { BeforeEach(func() {
calls = gosec.NewCallList() calls = gosec.NewCallList()
}) })

View file

@ -120,7 +120,7 @@ var (
// stdout the results as well as write it in the output file // stdout the results as well as write it in the output file
flagStdOut = flag.Bool("stdout", false, "Stdout the results as well as write it in the output file") flagStdOut = flag.Bool("stdout", false, "Stdout the results as well as write it in the output file")
//print the text report with color, this is enabled by default // print the text report with color, this is enabled by default
flagColor = flag.Bool("color", true, "Prints the text format report with colorization when it goes in the stdout") flagColor = flag.Bool("color", true, "Prints the text format report with colorization when it goes in the stdout")
// overrides the output format when stdout the results while saving them in the output file // overrides the output format when stdout the results while saving them in the output file
@ -209,7 +209,7 @@ func getRootPaths(paths []string) []string {
} }
func getPrintedFormat(format string, verbose string) string { func getPrintedFormat(format string, verbose string) string {
var fileFormat = format fileFormat := format
if format != "" && verbose != "" { if format != "" && verbose != "" {
fileFormat = verbose fileFormat = verbose
} }
@ -217,7 +217,6 @@ func getPrintedFormat(format string, verbose string) string {
} }
func printReport(format string, color bool, rootPaths []string, reportInfo *gosec.ReportInfo) error { func printReport(format string, color bool, rootPaths []string, reportInfo *gosec.ReportInfo) error {
err := report.CreateReport(os.Stdout, format, color, rootPaths, reportInfo) err := report.CreateReport(os.Stdout, format, color, rootPaths, reportInfo)
if err != nil { if err != nil {
return err return err
@ -226,7 +225,6 @@ func printReport(format string, color bool, rootPaths []string, reportInfo *gose
} }
func saveReport(filename, format string, rootPaths []string, reportInfo *gosec.ReportInfo) error { func saveReport(filename, format string, rootPaths []string, reportInfo *gosec.ReportInfo) error {
outfile, err := os.Create(filename) outfile, err := os.Create(filename)
if err != nil { if err != nil {
return err return err
@ -386,7 +384,7 @@ func main() {
reportInfo := gosec.NewReportInfo(issues, metrics, errors).WithVersion(Version) reportInfo := gosec.NewReportInfo(issues, metrics, errors).WithVersion(Version)
if *flagOutput == "" || *flagStdOut { if *flagOutput == "" || *flagStdOut {
var fileFormat = getPrintedFormat(*flagOutput, *flagVerbose) fileFormat := getPrintedFormat(*flagOutput, *flagVerbose)
if err := printReport(fileFormat, *flagColor, rootPaths, reportInfo); err != nil { if err := printReport(fileFormat, *flagColor, rootPaths, reportInfo); err != nil {
logger.Fatal((err)) logger.Fatal((err))
} }

View file

@ -12,7 +12,6 @@ import (
func extractLineNumber(s string) int { func extractLineNumber(s string) int {
lineNumber, _ := strconv.Atoi(strings.Split(s, "-")[0]) lineNumber, _ := strconv.Atoi(strings.Split(s, "-")[0])
return lineNumber return lineNumber
} }
type sortBySeverity []*gosec.Issue type sortBySeverity []*gosec.Issue

View file

@ -26,11 +26,13 @@ import (
"strings" "strings"
) )
type command func(args ...string) type (
type utilities struct { command func(args ...string)
commands map[string]command utilities struct {
call []string commands map[string]command
} call []string
}
)
// Custom commands / utilities to run instead of default analyzer // Custom commands / utilities to run instead of default analyzer
func newUtils() *utilities { func newUtils() *utilities {
@ -58,7 +60,6 @@ func (u *utilities) String() string {
func (u *utilities) Set(opt string) error { func (u *utilities) Set(opt string) error {
if _, ok := u.commands[opt]; !ok { if _, ok := u.commands[opt]; !ok {
return fmt.Errorf("valid tools are: %s", u.String()) return fmt.Errorf("valid tools are: %s", u.String())
} }
u.call = append(u.call, opt) u.call = append(u.call, opt)
return nil return nil
@ -171,7 +172,6 @@ func checkContext(ctx *context, file string) bool {
} }
func dumpCallObj(files ...string) { func dumpCallObj(files ...string) {
for _, file := range files { for _, file := range files {
if shouldSkip(file) { if shouldSkip(file) {
continue continue
@ -184,9 +184,9 @@ func dumpCallObj(files ...string) {
var obj types.Object var obj types.Object
switch node := n.(type) { switch node := n.(type) {
case *ast.Ident: case *ast.Ident:
obj = context.info.ObjectOf(node) //context.info.Uses[node] obj = context.info.ObjectOf(node) // context.info.Uses[node]
case *ast.SelectorExpr: case *ast.SelectorExpr:
obj = context.info.ObjectOf(node.Sel) //context.info.Uses[node.Sel] obj = context.info.ObjectOf(node.Sel) // context.info.Uses[node.Sel]
default: default:
obj = nil obj = nil
} }

View file

@ -56,7 +56,7 @@ func (c Config) convertGlobals() {
// ReadFrom implements the io.ReaderFrom interface. This // ReadFrom implements the io.ReaderFrom interface. This
// should be used with io.Reader to load configuration from // should be used with io.Reader to load configuration from
//file or from string etc. // file or from string etc.
func (c Config) ReadFrom(r io.Reader) (int64, error) { func (c Config) ReadFrom(r io.Reader) (int64, error) {
data, err := ioutil.ReadAll(r) data, err := ioutil.ReadAll(r)
if err != nil { if err != nil {

View file

@ -16,7 +16,6 @@ var _ = Describe("Configuration", func() {
}) })
Context("when loading from disk", func() { Context("when loading from disk", func() {
It("should be possible to load configuration from a file", func() { It("should be possible to load configuration from a file", func() {
json := `{"G101": {}}` json := `{"G101": {}}`
buffer := bytes.NewBufferString(json) buffer := bytes.NewBufferString(json)
@ -35,7 +34,6 @@ var _ = Describe("Configuration", func() {
_, err = configuration.ReadFrom(emptyBuffer) _, err = configuration.ReadFrom(emptyBuffer)
Expect(err).Should(HaveOccurred()) Expect(err).Should(HaveOccurred())
}) })
}) })
Context("when saving to disk", func() { Context("when saving to disk", func() {
@ -49,7 +47,6 @@ var _ = Describe("Configuration", func() {
}) })
It("should be possible to save configuration to file", func() { It("should be possible to save configuration to file", func() {
configuration.Set("G101", map[string]string{ configuration.Set("G101", map[string]string{
"mode": "strict", "mode": "strict",
}) })
@ -59,12 +56,10 @@ var _ = Describe("Configuration", func() {
Expect(int(nbytes)).ShouldNot(BeZero()) Expect(int(nbytes)).ShouldNot(BeZero())
Expect(err).ShouldNot(HaveOccurred()) Expect(err).ShouldNot(HaveOccurred())
Expect(buffer.String()).Should(Equal(`{"G101":{"mode":"strict"},"global":{}}`)) Expect(buffer.String()).Should(Equal(`{"G101":{"mode":"strict"},"global":{}}`))
}) })
}) })
Context("when configuring rules", func() { Context("when configuring rules", func() {
It("should be possible to get configuration for a rule", func() { It("should be possible to get configuration for a rule", func() {
settings := map[string]string{ settings := map[string]string{
"ciphers": "AES256-GCM", "ciphers": "AES256-GCM",

View file

@ -1,10 +1,10 @@
package cwe_test package cwe_test
import ( import (
"testing"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
"testing"
) )
func TestCwe(t *testing.T) { func TestCwe(t *testing.T) {

View file

@ -1,15 +1,15 @@
package cwe package cwe
const ( const (
//Acronym is the acronym of CWE // Acronym is the acronym of CWE
Acronym = "CWE" Acronym = "CWE"
//Version the CWE version // Version the CWE version
Version = "4.4" Version = "4.4"
//ReleaseDateUtc the release Date of CWE Version // ReleaseDateUtc the release Date of CWE Version
ReleaseDateUtc = "2021-03-15" ReleaseDateUtc = "2021-03-15"
//Organization MITRE // Organization MITRE
Organization = "MITRE" Organization = "MITRE"
//Description the description of CWE // Description the description of CWE
Description = "The MITRE Common Weakness Enumeration" Description = "The MITRE Common Weakness Enumeration"
) )
@ -126,7 +126,7 @@ func init() {
} }
} }
//Get Retrieves a CWE weakness by it's id // Get Retrieves a CWE weakness by it's id
func Get(id string) *Weakness { func Get(id string) *Weakness {
weakness, ok := data[id] weakness, ok := data[id]
if ok && weakness != nil { if ok && weakness != nil {

View file

@ -17,6 +17,5 @@ var _ = Describe("CWE data", func() {
Expect(weakness.Name).ShouldNot(BeNil()) Expect(weakness.Name).ShouldNot(BeNil())
Expect(weakness.Description).ShouldNot(BeNil()) Expect(weakness.Description).ShouldNot(BeNil())
}) })
}) })
}) })

View file

@ -12,17 +12,17 @@ type Weakness struct {
Description string Description string
} }
//SprintURL format the CWE URL // SprintURL format the CWE URL
func (w *Weakness) SprintURL() string { func (w *Weakness) SprintURL() string {
return fmt.Sprintf("https://cwe.mitre.org/data/definitions/%s.html", w.ID) return fmt.Sprintf("https://cwe.mitre.org/data/definitions/%s.html", w.ID)
} }
//SprintID format the CWE ID // SprintID format the CWE ID
func (w *Weakness) SprintID() string { func (w *Weakness) SprintID() string {
return fmt.Sprintf("%s-%s", Acronym, w.ID) return fmt.Sprintf("%s-%s", Acronym, w.ID)
} }
//MarshalJSON print only id and URL // MarshalJSON print only id and URL
func (w *Weakness) MarshalJSON() ([]byte, error) { func (w *Weakness) MarshalJSON() ([]byte, error) {
return json.Marshal(&struct { return json.Marshal(&struct {
ID string `json:"id"` ID string `json:"id"`
@ -33,12 +33,12 @@ func (w *Weakness) MarshalJSON() ([]byte, error) {
}) })
} }
//InformationURI link to the published CWE PDF // InformationURI link to the published CWE PDF
func InformationURI() string { func InformationURI() string {
return fmt.Sprintf("https://cwe.mitre.org/data/published/cwe_v%s.pdf/", Version) return fmt.Sprintf("https://cwe.mitre.org/data/published/cwe_v%s.pdf/", Version)
} }
//DownloadURI link to the zipped XML of the CWE list // DownloadURI link to the zipped XML of the CWE list
func DownloadURI() string { func DownloadURI() string {
return fmt.Sprintf("https://cwe.mitre.org/data/xml/cwec_v%s.xml.zip", Version) return fmt.Sprintf("https://cwe.mitre.org/data/xml/cwec_v%s.xml.zip", Version)
} }

View file

@ -1,10 +1,10 @@
package gosec_test package gosec_test
import ( import (
"testing"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
"testing"
) )
func TestGosec(t *testing.T) { func TestGosec(t *testing.T) {

View file

@ -168,7 +168,6 @@ func GetCallInfo(n ast.Node, ctx *Context) (string, string, error) {
} }
} }
} }
} }
} }
case *ast.Ident: case *ast.Ident:
@ -220,7 +219,6 @@ func GetIdentStringValues(ident *ast.Ident) []string {
} }
} }
} }
} }
return values return values
} }
@ -298,7 +296,7 @@ func Gopath() []string {
} }
// Getenv returns the values of the environment variable, otherwise // Getenv returns the values of the environment variable, otherwise
//returns the default if variable is not set // returns the default if variable is not set
func Getenv(key, userDefault string) string { func Getenv(key, userDefault string) string {
if val := os.Getenv(key); val != "" { if val := os.Getenv(key); val != "" {
return val return val

View file

@ -19,11 +19,12 @@ import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/securego/gosec/v2/cwe"
"go/ast" "go/ast"
"go/token" "go/token"
"os" "os"
"strconv" "strconv"
"github.com/securego/gosec/v2/cwe"
) )
// Score type used by severity and confidence values // Score type used by severity and confidence values

View file

@ -11,7 +11,6 @@ import (
) )
var _ = Describe("Issue", func() { var _ = Describe("Issue", func() {
Context("when creating a new issue", func() { Context("when creating a new issue", func() {
It("should create a code snippet from the specified ast.Node", func() { It("should create a code snippet from the specified ast.Node", func() {
var target *ast.BasicLit var target *ast.BasicLit
@ -134,7 +133,5 @@ func main() {
It("should maintain the provided confidence score", func() { It("should maintain the provided confidence score", func() {
Skip("Not implemented") Skip("Not implemented")
}) })
}) })
}) })

View file

@ -7,7 +7,7 @@ import (
"github.com/securego/gosec/v2" "github.com/securego/gosec/v2"
) )
//WriteReport write a report in csv format to the output writer // WriteReport write a report in csv format to the output writer
func WriteReport(w io.Writer, data *gosec.ReportInfo) error { func WriteReport(w io.Writer, data *gosec.ReportInfo) error {
out := csv.NewWriter(w) out := csv.NewWriter(w)
defer out.Flush() defer out.Flush()

View file

@ -1,10 +1,10 @@
package report package report
import ( import (
"testing"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
"testing"
) )
func TestRules(t *testing.T) { func TestRules(t *testing.T) {

View file

@ -272,15 +272,15 @@ var _ = Describe("Formatter", func() {
testSuite = junitReport.Testsuites[1] testSuite = junitReport.Testsuites[1]
Expect(testSuite.Testcases[0].Name).To(Equal(issues[1].File)) Expect(testSuite.Testcases[0].Name).To(Equal(issues[1].File))
}) })
}) })
Context("When using different report formats", func() { Context("When using different report formats", func() {
grules := []string{
grules := []string{"G101", "G102", "G103", "G104", "G106", "G101", "G102", "G103", "G104", "G106",
"G107", "G109", "G110", "G201", "G202", "G203", "G204", "G107", "G109", "G110", "G201", "G202", "G203", "G204",
"G301", "G302", "G303", "G304", "G305", "G401", "G402", "G301", "G302", "G303", "G304", "G305", "G401", "G402",
"G403", "G404", "G501", "G502", "G503", "G504", "G505"} "G403", "G404", "G501", "G502", "G503", "G504", "G505",
}
It("csv formatted report should contain the CWE mapping", func() { It("csv formatted report should contain the CWE mapping", func() {
for _, rule := range grules { for _, rule := range grules {

View file

@ -8,7 +8,7 @@ import (
"github.com/securego/gosec/v2" "github.com/securego/gosec/v2"
) )
//WriteReport write a report in golint format to the output writer // WriteReport write a report in golint format to the output writer
func WriteReport(w io.Writer, data *gosec.ReportInfo) error { func WriteReport(w io.Writer, data *gosec.ReportInfo) error {
// Output Sample: // Output Sample:
// /tmp/main.go:11:14: [CWE-310] RSA keys should be at least 2048 bits (Rule:G403, Severity:MEDIUM, Confidence:HIGH) // /tmp/main.go:11:14: [CWE-310] RSA keys should be at least 2048 bits (Rule:G403, Severity:MEDIUM, Confidence:HIGH)

View file

@ -7,7 +7,7 @@ import (
"github.com/securego/gosec/v2" "github.com/securego/gosec/v2"
) )
//WriteReport write a report in html format to the output writer // WriteReport write a report in html format to the output writer
func WriteReport(w io.Writer, data *gosec.ReportInfo) error { func WriteReport(w io.Writer, data *gosec.ReportInfo) error {
t, e := template.New("gosec").Parse(templateContent) t, e := template.New("gosec").Parse(templateContent)
if e != nil { if e != nil {

View file

@ -7,7 +7,7 @@ import (
"github.com/securego/gosec/v2" "github.com/securego/gosec/v2"
) )
//WriteReport write a report in json format to the output writer // WriteReport write a report in json format to the output writer
func WriteReport(w io.Writer, data *gosec.ReportInfo) error { func WriteReport(w io.Writer, data *gosec.ReportInfo) error {
raw, err := json.MarshalIndent(data, "", "\t") raw, err := json.MarshalIndent(data, "", "\t")
if err != nil { if err != nil {

View file

@ -1,13 +1,13 @@
package junit package junit
//NewTestsuite instantiate a Testsuite // NewTestsuite instantiate a Testsuite
func NewTestsuite(name string) *Testsuite { func NewTestsuite(name string) *Testsuite {
return &Testsuite{ return &Testsuite{
Name: name, Name: name,
} }
} }
//NewFailure instantiate a Failure // NewFailure instantiate a Failure
func NewFailure(message string, text string) *Failure { func NewFailure(message string, text string) *Failure {
return &Failure{ return &Failure{
Message: message, Message: message,
@ -15,7 +15,7 @@ func NewFailure(message string, text string) *Failure {
} }
} }
//NewTestcase instantiate a Testcase // NewTestcase instantiate a Testcase
func NewTestcase(name string, failure *Failure) *Testcase { func NewTestcase(name string, failure *Failure) *Testcase {
return &Testcase{ return &Testcase{
Name: name, Name: name,

View file

@ -15,7 +15,7 @@ func generatePlaintext(issue *gosec.Issue) string {
", CWE: " + issue.Cwe.ID + ")\n" + "> " + html.EscapeString(issue.Code) ", CWE: " + issue.Cwe.ID + ")\n" + "> " + html.EscapeString(issue.Code)
} }
//GenerateReport Convert a gosec report to a JUnit Report // GenerateReport Convert a gosec report to a JUnit Report
func GenerateReport(data *gosec.ReportInfo) Report { func GenerateReport(data *gosec.ReportInfo) Report {
var xmlReport Report var xmlReport Report
testsuites := map[string]int{} testsuites := map[string]int{}

View file

@ -4,13 +4,13 @@ import (
"encoding/xml" "encoding/xml"
) )
//Report defines a JUnit XML report // Report defines a JUnit XML report
type Report struct { type Report struct {
XMLName xml.Name `xml:"testsuites"` XMLName xml.Name `xml:"testsuites"`
Testsuites []*Testsuite `xml:"testsuite"` Testsuites []*Testsuite `xml:"testsuite"`
} }
//Testsuite defines a JUnit testsuite // Testsuite defines a JUnit testsuite
type Testsuite struct { type Testsuite struct {
XMLName xml.Name `xml:"testsuite"` XMLName xml.Name `xml:"testsuite"`
Name string `xml:"name,attr"` Name string `xml:"name,attr"`
@ -18,14 +18,14 @@ type Testsuite struct {
Testcases []*Testcase `xml:"testcase"` Testcases []*Testcase `xml:"testcase"`
} }
//Testcase defines a JUnit testcase // Testcase defines a JUnit testcase
type Testcase struct { type Testcase struct {
XMLName xml.Name `xml:"testcase"` XMLName xml.Name `xml:"testcase"`
Name string `xml:"name,attr"` Name string `xml:"name,attr"`
Failure *Failure `xml:"failure"` Failure *Failure `xml:"failure"`
} }
//Failure defines a JUnit failure // Failure defines a JUnit failure
type Failure struct { type Failure struct {
XMLName xml.Name `xml:"failure"` XMLName xml.Name `xml:"failure"`
Message string `xml:"message,attr"` Message string `xml:"message,attr"`

View file

@ -7,7 +7,7 @@ import (
"github.com/securego/gosec/v2" "github.com/securego/gosec/v2"
) )
//WriteReport write a report in JUnit format to the output writer // WriteReport write a report in JUnit format to the output writer
func WriteReport(w io.Writer, data *gosec.ReportInfo) error { func WriteReport(w io.Writer, data *gosec.ReportInfo) error {
junitXMLStruct := GenerateReport(data) junitXMLStruct := GenerateReport(data)
raw, err := xml.MarshalIndent(junitXMLStruct, "", "\t") raw, err := xml.MarshalIndent(junitXMLStruct, "", "\t")

View file

@ -1,6 +1,6 @@
package sarif package sarif
//NewReport instantiate a SARIF Report // NewReport instantiate a SARIF Report
func NewReport(version string, schema string) *Report { func NewReport(version string, schema string) *Report {
return &Report{ return &Report{
Version: version, Version: version,
@ -8,46 +8,46 @@ func NewReport(version string, schema string) *Report {
} }
} }
//WithRuns dafines runs for the current report // WithRuns dafines runs for the current report
func (r *Report) WithRuns(runs ...*Run) *Report { func (r *Report) WithRuns(runs ...*Run) *Report {
r.Runs = runs r.Runs = runs
return r return r
} }
//NewMultiformatMessageString instantiate a MultiformatMessageString // NewMultiformatMessageString instantiate a MultiformatMessageString
func NewMultiformatMessageString(text string) *MultiformatMessageString { func NewMultiformatMessageString(text string) *MultiformatMessageString {
return &MultiformatMessageString{ return &MultiformatMessageString{
Text: text, Text: text,
} }
} }
//NewRun instantiate a Run // NewRun instantiate a Run
func NewRun(tool *Tool) *Run { func NewRun(tool *Tool) *Run {
return &Run{ return &Run{
Tool: tool, Tool: tool,
} }
} }
//WithTaxonomies set the taxonomies for the current run // WithTaxonomies set the taxonomies for the current run
func (r *Run) WithTaxonomies(taxonomies ...*ToolComponent) *Run { func (r *Run) WithTaxonomies(taxonomies ...*ToolComponent) *Run {
r.Taxonomies = taxonomies r.Taxonomies = taxonomies
return r return r
} }
//WithResults set the results for the current run // WithResults set the results for the current run
func (r *Run) WithResults(results ...*Result) *Run { func (r *Run) WithResults(results ...*Result) *Run {
r.Results = results r.Results = results
return r return r
} }
//NewArtifactLocation instantiate an ArtifactLocation // NewArtifactLocation instantiate an ArtifactLocation
func NewArtifactLocation(uri string) *ArtifactLocation { func NewArtifactLocation(uri string) *ArtifactLocation {
return &ArtifactLocation{ return &ArtifactLocation{
URI: uri, URI: uri,
} }
} }
//NewRegion instantiate a Region // NewRegion instantiate a Region
func NewRegion(startLine int, endLine int, startColumn int, endColumn int, sourceLanguage string) *Region { func NewRegion(startLine int, endLine int, startColumn int, endColumn int, sourceLanguage string) *Region {
return &Region{ return &Region{
StartLine: startLine, StartLine: startLine,
@ -58,27 +58,27 @@ func NewRegion(startLine int, endLine int, startColumn int, endColumn int, sourc
} }
} }
//WithSnippet defines the Snippet for the current Region // WithSnippet defines the Snippet for the current Region
func (r *Region) WithSnippet(snippet *ArtifactContent) *Region { func (r *Region) WithSnippet(snippet *ArtifactContent) *Region {
r.Snippet = snippet r.Snippet = snippet
return r return r
} }
//NewArtifactContent instantiate an ArtifactContent // NewArtifactContent instantiate an ArtifactContent
func NewArtifactContent(text string) *ArtifactContent { func NewArtifactContent(text string) *ArtifactContent {
return &ArtifactContent{ return &ArtifactContent{
Text: text, Text: text,
} }
} }
//NewTool instantiate a Tool // NewTool instantiate a Tool
func NewTool(driver *ToolComponent) *Tool { func NewTool(driver *ToolComponent) *Tool {
return &Tool{ return &Tool{
Driver: driver, Driver: driver,
} }
} }
//NewResult instantiate a Result // NewResult instantiate a Result
func NewResult(ruleID string, ruleIndex int, level Level, message string) *Result { func NewResult(ruleID string, ruleIndex int, level Level, message string) *Result {
return &Result{ return &Result{
RuleID: ruleID, RuleID: ruleID,
@ -88,27 +88,27 @@ func NewResult(ruleID string, ruleIndex int, level Level, message string) *Resul
} }
} }
//NewMessage instantiate a Message // NewMessage instantiate a Message
func NewMessage(text string) *Message { func NewMessage(text string) *Message {
return &Message{ return &Message{
Text: text, Text: text,
} }
} }
//WithLocations define the current result's locations // WithLocations define the current result's locations
func (r *Result) WithLocations(locations ...*Location) *Result { func (r *Result) WithLocations(locations ...*Location) *Result {
r.Locations = locations r.Locations = locations
return r return r
} }
//NewLocation instantiate a Location // NewLocation instantiate a Location
func NewLocation(physicalLocation *PhysicalLocation) *Location { func NewLocation(physicalLocation *PhysicalLocation) *Location {
return &Location{ return &Location{
PhysicalLocation: physicalLocation, PhysicalLocation: physicalLocation,
} }
} }
//NewPhysicalLocation instantiate a PhysicalLocation // NewPhysicalLocation instantiate a PhysicalLocation
func NewPhysicalLocation(artifactLocation *ArtifactLocation, region *Region) *PhysicalLocation { func NewPhysicalLocation(artifactLocation *ArtifactLocation, region *Region) *PhysicalLocation {
return &PhysicalLocation{ return &PhysicalLocation{
ArtifactLocation: artifactLocation, ArtifactLocation: artifactLocation,
@ -116,7 +116,7 @@ func NewPhysicalLocation(artifactLocation *ArtifactLocation, region *Region) *Ph
} }
} }
//NewToolComponent instantiate a ToolComponent // NewToolComponent instantiate a ToolComponent
func NewToolComponent(name string, version string, informationURI string) *ToolComponent { func NewToolComponent(name string, version string, informationURI string) *ToolComponent {
return &ToolComponent{ return &ToolComponent{
Name: name, Name: name,
@ -126,73 +126,73 @@ func NewToolComponent(name string, version string, informationURI string) *ToolC
} }
} }
//WithLanguage set Language for the current ToolComponent // WithLanguage set Language for the current ToolComponent
func (t *ToolComponent) WithLanguage(language string) *ToolComponent { func (t *ToolComponent) WithLanguage(language string) *ToolComponent {
t.Language = language t.Language = language
return t return t
} }
//WithSemanticVersion set SemanticVersion for the current ToolComponent // WithSemanticVersion set SemanticVersion for the current ToolComponent
func (t *ToolComponent) WithSemanticVersion(semanticVersion string) *ToolComponent { func (t *ToolComponent) WithSemanticVersion(semanticVersion string) *ToolComponent {
t.SemanticVersion = semanticVersion t.SemanticVersion = semanticVersion
return t return t
} }
//WithReleaseDateUtc set releaseDateUtc for the current ToolComponent // WithReleaseDateUtc set releaseDateUtc for the current ToolComponent
func (t *ToolComponent) WithReleaseDateUtc(releaseDateUtc string) *ToolComponent { func (t *ToolComponent) WithReleaseDateUtc(releaseDateUtc string) *ToolComponent {
t.ReleaseDateUtc = releaseDateUtc t.ReleaseDateUtc = releaseDateUtc
return t return t
} }
//WithDownloadURI set downloadURI for the current ToolComponent // WithDownloadURI set downloadURI for the current ToolComponent
func (t *ToolComponent) WithDownloadURI(downloadURI string) *ToolComponent { func (t *ToolComponent) WithDownloadURI(downloadURI string) *ToolComponent {
t.DownloadURI = downloadURI t.DownloadURI = downloadURI
return t return t
} }
//WithOrganization set organization for the current ToolComponent // WithOrganization set organization for the current ToolComponent
func (t *ToolComponent) WithOrganization(organization string) *ToolComponent { func (t *ToolComponent) WithOrganization(organization string) *ToolComponent {
t.Organization = organization t.Organization = organization
return t return t
} }
//WithShortDescription set shortDescription for the current ToolComponent // WithShortDescription set shortDescription for the current ToolComponent
func (t *ToolComponent) WithShortDescription(shortDescription *MultiformatMessageString) *ToolComponent { func (t *ToolComponent) WithShortDescription(shortDescription *MultiformatMessageString) *ToolComponent {
t.ShortDescription = shortDescription t.ShortDescription = shortDescription
return t return t
} }
//WithIsComprehensive set isComprehensive for the current ToolComponent // WithIsComprehensive set isComprehensive for the current ToolComponent
func (t *ToolComponent) WithIsComprehensive(isComprehensive bool) *ToolComponent { func (t *ToolComponent) WithIsComprehensive(isComprehensive bool) *ToolComponent {
t.IsComprehensive = isComprehensive t.IsComprehensive = isComprehensive
return t return t
} }
//WithMinimumRequiredLocalizedDataSemanticVersion set MinimumRequiredLocalizedDataSemanticVersion for the current ToolComponent // WithMinimumRequiredLocalizedDataSemanticVersion set MinimumRequiredLocalizedDataSemanticVersion for the current ToolComponent
func (t *ToolComponent) WithMinimumRequiredLocalizedDataSemanticVersion(minimumRequiredLocalizedDataSemanticVersion string) *ToolComponent { func (t *ToolComponent) WithMinimumRequiredLocalizedDataSemanticVersion(minimumRequiredLocalizedDataSemanticVersion string) *ToolComponent {
t.MinimumRequiredLocalizedDataSemanticVersion = minimumRequiredLocalizedDataSemanticVersion t.MinimumRequiredLocalizedDataSemanticVersion = minimumRequiredLocalizedDataSemanticVersion
return t return t
} }
//WithTaxa set taxa for the current ToolComponent // WithTaxa set taxa for the current ToolComponent
func (t *ToolComponent) WithTaxa(taxa ...*ReportingDescriptor) *ToolComponent { func (t *ToolComponent) WithTaxa(taxa ...*ReportingDescriptor) *ToolComponent {
t.Taxa = taxa t.Taxa = taxa
return t return t
} }
//WithSupportedTaxonomies set the supported taxonomies for the current ToolComponent // WithSupportedTaxonomies set the supported taxonomies for the current ToolComponent
func (t *ToolComponent) WithSupportedTaxonomies(supportedTaxonomies ...*ToolComponentReference) *ToolComponent { func (t *ToolComponent) WithSupportedTaxonomies(supportedTaxonomies ...*ToolComponentReference) *ToolComponent {
t.SupportedTaxonomies = supportedTaxonomies t.SupportedTaxonomies = supportedTaxonomies
return t return t
} }
//WithRules set the rules for the current ToolComponent // WithRules set the rules for the current ToolComponent
func (t *ToolComponent) WithRules(rules ...*ReportingDescriptor) *ToolComponent { func (t *ToolComponent) WithRules(rules ...*ReportingDescriptor) *ToolComponent {
t.Rules = rules t.Rules = rules
return t return t
} }
//NewToolComponentReference instantiate a ToolComponentReference // NewToolComponentReference instantiate a ToolComponentReference
func NewToolComponentReference(name string) *ToolComponentReference { func NewToolComponentReference(name string) *ToolComponentReference {
return &ToolComponentReference{ return &ToolComponentReference{
Name: name, Name: name,

View file

@ -1,22 +1,22 @@
package sarif package sarif
//Level SARIF level // Level SARIF level
// From https://docs.oasis-open.org/sarif/sarif/v2.0/csprd02/sarif-v2.0-csprd02.html#_Toc10127839 // From https://docs.oasis-open.org/sarif/sarif/v2.0/csprd02/sarif-v2.0-csprd02.html#_Toc10127839
type Level string type Level string
const ( const (
//None : The concept of “severity” does not apply to this result because the kind // None : The concept of “severity” does not apply to this result because the kind
// property (§3.27.9) has a value other than "fail". // property (§3.27.9) has a value other than "fail".
None = Level("none") None = Level("none")
//Note : The rule specified by ruleId was evaluated and a minor problem or an opportunity // Note : The rule specified by ruleId was evaluated and a minor problem or an opportunity
// to improve the code was found. // to improve the code was found.
Note = Level("note") Note = Level("note")
//Warning : The rule specified by ruleId was evaluated and a problem was found. // Warning : The rule specified by ruleId was evaluated and a problem was found.
Warning = Level("warning") Warning = Level("warning")
//Error : The rule specified by ruleId was evaluated and a serious problem was found. // Error : The rule specified by ruleId was evaluated and a serious problem was found.
Error = Level("error") Error = Level("error")
//Version : SARIF Schema version // Version : SARIF Schema version
Version = "2.1.0" Version = "2.1.0"
//Schema : SARIF Schema URL // Schema : SARIF Schema URL
Schema = "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json" Schema = "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json"
) )

View file

@ -12,9 +12,8 @@ import (
"github.com/securego/gosec/v2/cwe" "github.com/securego/gosec/v2/cwe"
) )
//GenerateReport Convert a gosec report to a Sarif Report // GenerateReport Convert a gosec report to a Sarif Report
func GenerateReport(rootPaths []string, data *gosec.ReportInfo) (*Report, error) { func GenerateReport(rootPaths []string, data *gosec.ReportInfo) (*Report, error) {
type rule struct { type rule struct {
index int index int
rule *ReportingDescriptor rule *ReportingDescriptor

View file

@ -7,7 +7,7 @@ import (
"github.com/securego/gosec/v2" "github.com/securego/gosec/v2"
) )
//WriteReport write a report in SARIF format to the output writer // WriteReport write a report in SARIF format to the output writer
func WriteReport(w io.Writer, data *gosec.ReportInfo, rootPaths []string) error { func WriteReport(w io.Writer, data *gosec.ReportInfo, rootPaths []string) error {
sr, err := GenerateReport(rootPaths, data) sr, err := GenerateReport(rootPaths, data)
if err != nil { if err != nil {

View file

@ -1,6 +1,6 @@
package sonar package sonar
//NewLocation instantiate a Location // NewLocation instantiate a Location
func NewLocation(message string, filePath string, textRange *TextRange) *Location { func NewLocation(message string, filePath string, textRange *TextRange) *Location {
return &Location{ return &Location{
Message: message, Message: message,
@ -9,7 +9,7 @@ func NewLocation(message string, filePath string, textRange *TextRange) *Locatio
} }
} }
//NewTextRange instantiate a TextRange // NewTextRange instantiate a TextRange
func NewTextRange(startLine int, endLine int) *TextRange { func NewTextRange(startLine int, endLine int) *TextRange {
return &TextRange{ return &TextRange{
StartLine: startLine, StartLine: startLine,
@ -17,7 +17,7 @@ func NewTextRange(startLine int, endLine int) *TextRange {
} }
} }
//NewIssue instantiate an Issue // NewIssue instantiate an Issue
func NewIssue(engineID string, ruleID string, primaryLocation *Location, issueType string, severity string, effortMinutes int) *Issue { func NewIssue(engineID string, ruleID string, primaryLocation *Location, issueType string, severity string, effortMinutes int) *Issue {
return &Issue{ return &Issue{
EngineID: engineID, EngineID: engineID,

View file

@ -8,11 +8,11 @@ import (
) )
const ( const (
//EffortMinutes effort to fix in minutes // EffortMinutes effort to fix in minutes
EffortMinutes = 5 EffortMinutes = 5
) )
//GenerateReport Convert a gosec report to a Sonar Report // GenerateReport Convert a gosec report to a Sonar Report
func GenerateReport(rootPaths []string, data *gosec.ReportInfo) (*Report, error) { func GenerateReport(rootPaths []string, data *gosec.ReportInfo) (*Report, error) {
si := &Report{Issues: []*Issue{}} si := &Report{Issues: []*Issue{}}
for _, issue := range data.Issues { for _, issue := range data.Issues {

View file

@ -1,10 +1,10 @@
package sonar_test package sonar_test
import ( import (
"testing"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
"testing"
) )
func TestRules(t *testing.T) { func TestRules(t *testing.T) {

View file

@ -1,6 +1,6 @@
package sonar package sonar
//TextRange defines the text range of an issue's location // TextRange defines the text range of an issue's location
type TextRange struct { type TextRange struct {
StartLine int `json:"startLine"` StartLine int `json:"startLine"`
EndLine int `json:"endLine"` EndLine int `json:"endLine"`
@ -8,14 +8,14 @@ type TextRange struct {
EtartColumn int `json:"endColumn,omitempty"` EtartColumn int `json:"endColumn,omitempty"`
} }
//Location defines a sonar issue's location // Location defines a sonar issue's location
type Location struct { type Location struct {
Message string `json:"message"` Message string `json:"message"`
FilePath string `json:"filePath"` FilePath string `json:"filePath"`
TextRange *TextRange `json:"textRange,omitempty"` TextRange *TextRange `json:"textRange,omitempty"`
} }
//Issue defines a sonar issue // Issue defines a sonar issue
type Issue struct { type Issue struct {
EngineID string `json:"engineId"` EngineID string `json:"engineId"`
RuleID string `json:"ruleId"` RuleID string `json:"ruleId"`
@ -26,7 +26,7 @@ type Issue struct {
SecondaryLocations []*Location `json:"secondaryLocations,omitempty"` SecondaryLocations []*Location `json:"secondaryLocations,omitempty"`
} }
//Report defines a sonar report // Report defines a sonar report
type Report struct { type Report struct {
Issues []*Issue `json:"issues"` Issues []*Issue `json:"issues"`
} }

View file

@ -7,7 +7,7 @@ import (
"github.com/securego/gosec/v2" "github.com/securego/gosec/v2"
) )
//WriteReport write a report in sonar format to the output writer // WriteReport write a report in sonar format to the output writer
func WriteReport(w io.Writer, data *gosec.ReportInfo, rootPaths []string) error { func WriteReport(w io.Writer, data *gosec.ReportInfo, rootPaths []string) error {
si, err := GenerateReport(rootPaths, data) si, err := GenerateReport(rootPaths, data)
if err != nil { if err != nil {

View file

@ -19,7 +19,7 @@ var (
defaultTheme = color.New(color.FgWhite, color.BgBlack) defaultTheme = color.New(color.FgWhite, color.BgBlack)
) )
//WriteReport write a (colorized) report in text format // WriteReport write a (colorized) report in text format
func WriteReport(w io.Writer, data *gosec.ReportInfo, enableColor bool) error { func WriteReport(w io.Writer, data *gosec.ReportInfo, enableColor bool) error {
t, e := template. t, e := template.
New("gosec"). New("gosec").

View file

@ -7,7 +7,7 @@ import (
"gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
) )
//WriteReport write a report in yaml format to the output writer // WriteReport write a report in yaml format to the output writer
func WriteReport(w io.Writer, data *gosec.ReportInfo) error { func WriteReport(w io.Writer, data *gosec.ReportInfo) error {
raw, err := yaml.Marshal(data) raw, err := yaml.Marshal(data)
if err != nil { if err != nil {

View file

@ -336,6 +336,5 @@ var _ = Describe("Resolve ast node to concrete value", func() {
Expect(value).ShouldNot(BeNil()) Expect(value).ShouldNot(BeNil())
Expect(gosec.TryResolve(value, ctx)).Should(BeFalse()) Expect(gosec.TryResolve(value, ctx)).Should(BeFalse())
}) })
}) })
}) })

View file

@ -27,9 +27,7 @@ func (m *mockrule) Match(n ast.Node, ctx *gosec.Context) (*gosec.Issue, error) {
} }
var _ = Describe("Rule", func() { var _ = Describe("Rule", func() {
Context("when using a ruleset", func() { Context("when using a ruleset", func() {
var ( var (
ruleset gosec.RuleSet ruleset gosec.RuleSet
dummyErrorRule gosec.Rule dummyErrorRule gosec.Rule
@ -65,7 +63,6 @@ var _ = Describe("Rule", func() {
Expect(ruleset.RegisteredFor(unregisteredNode)).Should(BeEmpty()) Expect(ruleset.RegisteredFor(unregisteredNode)).Should(BeEmpty())
Expect(ruleset.RegisteredFor(registeredNodeA)).Should(ContainElement(dummyIssueRule)) Expect(ruleset.RegisteredFor(registeredNodeA)).Should(ContainElement(dummyIssueRule))
Expect(ruleset.RegisteredFor(registeredNodeB)).Should(ContainElement(dummyIssueRule)) Expect(ruleset.RegisteredFor(registeredNodeB)).Should(ContainElement(dummyIssueRule))
}) })
It("should not register a rule when no ast.Nodes are specified", func() { It("should not register a rule when no ast.Nodes are specified", func() {
@ -83,7 +80,5 @@ var _ = Describe("Rule", func() {
Expect(ruleset.RegisteredFor(registeredNode)).Should(ContainElement(dummyErrorRule)) Expect(ruleset.RegisteredFor(registeredNode)).Should(ContainElement(dummyErrorRule))
Expect(ruleset.RegisteredFor(registeredNode)).Should(ContainElement(dummyIssueRule)) Expect(ruleset.RegisteredFor(registeredNode)).Should(ContainElement(dummyIssueRule))
}) })
}) })
}) })

View file

@ -44,7 +44,6 @@ func (r *badDefer) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
} }
} }
} }
} }
return nil, nil return nil, nil

View file

@ -34,7 +34,7 @@ func (r *filePermissions) ID() string {
} }
func getConfiguredMode(conf map[string]interface{}, configKey string, defaultMode int64) int64 { func getConfiguredMode(conf map[string]interface{}, configKey string, defaultMode int64) int64 {
var mode = defaultMode mode := defaultMode
if value, ok := conf[configKey]; ok { if value, ok := conf[configKey]; ok {
switch value := value.(type) { switch value := value.(type) {
case int64: case int64:

View file

@ -121,7 +121,7 @@ func NewHardcodedCredentials(id string, conf gosec.Config) (gosec.Rule, []ast.No
entropyThreshold := 80.0 entropyThreshold := 80.0
perCharThreshold := 3.0 perCharThreshold := 3.0
ignoreEntropy := false ignoreEntropy := false
var truncateString = 16 truncateString := 16
if val, ok := conf["G101"]; ok { if val, ok := conf["G101"]; ok {
conf := val.(map[string]interface{}) conf := val.(map[string]interface{})
if configPattern, ok := conf["pattern"]; ok { if configPattern, ok := conf["pattern"]; ok {

View file

@ -43,8 +43,10 @@ func (w *weakRand) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
// NewWeakRandCheck detects the use of random number generator that isn't cryptographically secure // NewWeakRandCheck detects the use of random number generator that isn't cryptographically secure
func NewWeakRandCheck(id string, conf gosec.Config) (gosec.Rule, []ast.Node) { func NewWeakRandCheck(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
return &weakRand{ return &weakRand{
funcNames: []string{"New", "Read", "Float32", "Float64", "Int", "Int31", funcNames: []string{
"Int31n", "Int63", "Int63n", "Intn", "NormalFloat64", "Uint32", "Uint64"}, "New", "Read", "Float32", "Float64", "Int", "Int31",
"Int31n", "Int63", "Int63n", "Intn", "NormalFloat64", "Uint32", "Uint64",
},
packagePath: "math/rand", packagePath: "math/rand",
MetaData: gosec.MetaData{ MetaData: gosec.MetaData{
ID: id, ID: id,

View file

@ -1,10 +1,10 @@
package rules_test package rules_test
import ( import (
"testing"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
"testing"
) )
func TestRules(t *testing.T) { func TestRules(t *testing.T) {

View file

@ -13,7 +13,6 @@ import (
) )
var _ = Describe("gosec rules", func() { var _ = Describe("gosec rules", func() {
var ( var (
logger *log.Logger logger *log.Logger
config gosec.Config config gosec.Config
@ -179,7 +178,5 @@ var _ = Describe("gosec rules", func() {
It("should detect implicit aliasing in ForRange", func() { It("should detect implicit aliasing in ForRange", func() {
runner("G601", testutils.SampleCodeG601) runner("G601", testutils.SampleCodeG601)
}) })
}) })
}) })

View file

@ -186,7 +186,7 @@ func (s *sqlStrFormat) checkQuery(call *ast.CallExpr, ctx *gosec.Context) (*gose
decl := ident.Obj.Decl decl := ident.Obj.Decl
if assign, ok := decl.(*ast.AssignStmt); ok { if assign, ok := decl.(*ast.AssignStmt); ok {
for _, expr := range assign.Rhs { for _, expr := range assign.Rhs {
issue, err := s.checkFormatting(expr, ctx) issue := s.checkFormatting(expr, ctx)
if issue != nil { if issue != nil {
return issue, err return issue, err
} }
@ -197,7 +197,7 @@ func (s *sqlStrFormat) checkQuery(call *ast.CallExpr, ctx *gosec.Context) (*gose
return nil, nil return nil, nil
} }
func (s *sqlStrFormat) checkFormatting(n ast.Node, ctx *gosec.Context) (*gosec.Issue, error) { func (s *sqlStrFormat) checkFormatting(n ast.Node, ctx *gosec.Context) *gosec.Issue {
// argIndex changes the function argument which gets matched to the regex // argIndex changes the function argument which gets matched to the regex
argIndex := 0 argIndex := 0
if node := s.fmtCalls.ContainsPkgCallExpr(n, ctx, false); node != nil { if node := s.fmtCalls.ContainsPkgCallExpr(n, ctx, false); node != nil {
@ -208,7 +208,7 @@ func (s *sqlStrFormat) checkFormatting(n ast.Node, ctx *gosec.Context) (*gosec.I
if arg, ok := node.Args[0].(*ast.SelectorExpr); ok { if arg, ok := node.Args[0].(*ast.SelectorExpr); ok {
if ident, ok := arg.X.(*ast.Ident); ok { if ident, ok := arg.X.(*ast.Ident); ok {
if s.noIssue.Contains(ident.Name, arg.Sel.Name) { if s.noIssue.Contains(ident.Name, arg.Sel.Name) {
return nil, nil return nil
} }
} }
} }
@ -219,7 +219,7 @@ func (s *sqlStrFormat) checkFormatting(n ast.Node, ctx *gosec.Context) (*gosec.I
// no formatter // no formatter
if len(node.Args) == 0 { if len(node.Args) == 0 {
return nil, nil return nil
} }
var formatter string var formatter string
@ -233,7 +233,7 @@ func (s *sqlStrFormat) checkFormatting(n ast.Node, ctx *gosec.Context) (*gosec.I
formatter = arg formatter = arg
} }
if len(formatter) <= 0 { if len(formatter) <= 0 {
return nil, nil return nil
} }
// If all formatter args are quoted or constant, then the SQL construction is safe // If all formatter args are quoted or constant, then the SQL construction is safe
@ -246,14 +246,14 @@ func (s *sqlStrFormat) checkFormatting(n ast.Node, ctx *gosec.Context) (*gosec.I
} }
} }
if allSafe { if allSafe {
return nil, nil return nil
} }
} }
if s.MatchPatterns(formatter) { if s.MatchPatterns(formatter) {
return gosec.NewIssue(ctx, n, s.ID(), s.What, s.Severity, s.Confidence), nil return gosec.NewIssue(ctx, n, s.ID(), s.What, s.Severity, s.Confidence)
} }
} }
return nil, nil return nil
} }
// Check SQL query formatting issues such as "fmt.Sprintf("SELECT * FROM foo where '%s', userInput)" // Check SQL query formatting issues such as "fmt.Sprintf("SELECT * FROM foo where '%s', userInput)"

View file

@ -43,7 +43,6 @@ func (t *templateCheck) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error
// NewTemplateCheck constructs the template check rule. This rule is used to // NewTemplateCheck constructs the template check rule. This rule is used to
// find use of templates where HTML/JS escaping is not being used // find use of templates where HTML/JS escaping is not being used
func NewTemplateCheck(id string, conf gosec.Config) (gosec.Rule, []ast.Node) { func NewTemplateCheck(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
calls := gosec.NewCallList() calls := gosec.NewCallList()
calls.Add("html/template", "HTML") calls.Add("html/template", "HTML")
calls.Add("html/template", "HTMLAttr") calls.Add("html/template", "HTMLAttr")

View file

@ -112,7 +112,6 @@ func (t *insecureConfigTLS) processTLSConfVal(n *ast.KeyValueExpr, c *gosec.Cont
} }
} }
} }
return nil return nil
} }

View file

@ -11,14 +11,16 @@ type CodeSample struct {
var ( var (
// SampleCodeG101 code snippets for hardcoded credentials // SampleCodeG101 code snippets for hardcoded credentials
SampleCodeG101 = []CodeSample{{[]string{` SampleCodeG101 = []CodeSample{
{[]string{`
package main package main
import "fmt" import "fmt"
func main() { func main() {
username := "admin" username := "admin"
password := "f62e5bcda4fae4f82370da0c6f20697b8f8447ef" password := "f62e5bcda4fae4f82370da0c6f20697b8f8447ef"
fmt.Println("Doing something with: ", username, password) fmt.Println("Doing something with: ", username, password)
}`}, 1, gosec.NewConfig()}, {[]string{` }`}, 1, gosec.NewConfig()},
{[]string{`
// Entropy check should not report this error by default // Entropy check should not report this error by default
package main package main
import "fmt" import "fmt"
@ -26,21 +28,24 @@ func main() {
username := "admin" username := "admin"
password := "secret" password := "secret"
fmt.Println("Doing something with: ", username, password) fmt.Println("Doing something with: ", username, password)
}`}, 0, gosec.NewConfig()}, {[]string{` }`}, 0, gosec.NewConfig()},
{[]string{`
package main package main
import "fmt" import "fmt"
var password = "f62e5bcda4fae4f82370da0c6f20697b8f8447ef" var password = "f62e5bcda4fae4f82370da0c6f20697b8f8447ef"
func main() { func main() {
username := "admin" username := "admin"
fmt.Println("Doing something with: ", username, password) fmt.Println("Doing something with: ", username, password)
}`}, 1, gosec.NewConfig()}, {[]string{` }`}, 1, gosec.NewConfig()},
{[]string{`
package main package main
import "fmt" import "fmt"
const password = "f62e5bcda4fae4f82370da0c6f20697b8f8447ef" const password = "f62e5bcda4fae4f82370da0c6f20697b8f8447ef"
func main() { func main() {
username := "admin" username := "admin"
fmt.Println("Doing something with: ", username, password) fmt.Println("Doing something with: ", username, password)
}`}, 1, gosec.NewConfig()}, {[]string{` }`}, 1, gosec.NewConfig()},
{[]string{`
package main package main
import "fmt" import "fmt"
const ( const (
@ -49,12 +54,14 @@ const (
) )
func main() { func main() {
fmt.Println("Doing something with: ", username, password) fmt.Println("Doing something with: ", username, password)
}`}, 1, gosec.NewConfig()}, {[]string{` }`}, 1, gosec.NewConfig()},
{[]string{`
package main package main
var password string var password string
func init() { func init() {
password = "f62e5bcda4fae4f82370da0c6f20697b8f8447ef" password = "f62e5bcda4fae4f82370da0c6f20697b8f8447ef"
}`}, 1, gosec.NewConfig()}, {[]string{` }`}, 1, gosec.NewConfig()},
{[]string{`
package main package main
const ( const (
ATNStateSomethingElse = 1 ATNStateSomethingElse = 1
@ -62,7 +69,8 @@ const (
) )
func main() { func main() {
println(ATNStateTokenStart) println(ATNStateTokenStart)
}`}, 0, gosec.NewConfig()}, {[]string{` }`}, 0, gosec.NewConfig()},
{[]string{`
package main package main
const ( const (
ATNStateTokenStart = "f62e5bcda4fae4f82370da0c6f20697b8f8447ef" ATNStateTokenStart = "f62e5bcda4fae4f82370da0c6f20697b8f8447ef"
@ -96,7 +104,8 @@ func main() {
if p != "f62e5bcda4fae4f82370da0c6f20697b8f8447ef" { if p != "f62e5bcda4fae4f82370da0c6f20697b8f8447ef" {
fmt.Println("password equality") fmt.Println("password equality")
} }
}`}, 0, gosec.NewConfig()}} }`}, 0, gosec.NewConfig()},
}
// SampleCodeG102 code snippets for network binding // SampleCodeG102 code snippets for network binding
SampleCodeG102 = []CodeSample{ SampleCodeG102 = []CodeSample{
@ -201,7 +210,8 @@ func main() {
addressHolder := uintptr(unsafe.Pointer(intPtr)) + unsafe.Sizeof(intArray[0]) addressHolder := uintptr(unsafe.Pointer(intPtr)) + unsafe.Sizeof(intArray[0])
intPtr = (*int)(unsafe.Pointer(addressHolder)) intPtr = (*int)(unsafe.Pointer(addressHolder))
fmt.Printf("\nintPtr=%p, *intPtr=%d.\n\n", intPtr, *intPtr) fmt.Printf("\nintPtr=%p, *intPtr=%d.\n\n", intPtr, *intPtr)
}`}, 3, gosec.NewConfig()}} }`}, 3, gosec.NewConfig()},
}
// SampleCodeG104 finds errors that aren't being handled // SampleCodeG104 finds errors that aren't being handled
SampleCodeG104 = []CodeSample{ SampleCodeG104 = []CodeSample{
@ -314,7 +324,8 @@ func main() {
createBuffer().WriteString("*bytes.Buffer") createBuffer().WriteString("*bytes.Buffer")
b := createBuffer() b := createBuffer()
b.WriteString("*bytes.Buffer") b.WriteString("*bytes.Buffer")
}`}, 0, gosec.NewConfig()}} // it shoudn't return any errors because all method calls are whitelisted by default }`}, 0, gosec.NewConfig()},
} // it shoudn't return any errors because all method calls are whitelisted by default
// SampleCodeG104Audit finds errors that aren't being handled in audit mode // SampleCodeG104Audit finds errors that aren't being handled in audit mode
SampleCodeG104Audit = []CodeSample{ SampleCodeG104Audit = []CodeSample{
@ -372,7 +383,8 @@ func main() {
}`, ` }`, `
package main package main
func dummy(){} func dummy(){}
`}, 0, gosec.Config{gosec.Globals: map[gosec.GlobalOption]string{gosec.Audit: "enabled"}}}} `}, 0, gosec.Config{gosec.Globals: map[gosec.GlobalOption]string{gosec.Audit: "enabled"}}},
}
// SampleCodeG106 - ssh InsecureIgnoreHostKey // SampleCodeG106 - ssh InsecureIgnoreHostKey
SampleCodeG106 = []CodeSample{{[]string{` SampleCodeG106 = []CodeSample{{[]string{`
@ -675,7 +687,8 @@ func main() {
} }
v := int32(value) v := int32(value)
fmt.Println(v) fmt.Println(v)
}`}, 0, gosec.NewConfig()}} }`}, 0, gosec.NewConfig()},
}
// SampleCodeG110 - potential DoS vulnerability via decompression bomb // SampleCodeG110 - potential DoS vulnerability via decompression bomb
SampleCodeG110 = []CodeSample{ SampleCodeG110 = []CodeSample{
@ -791,7 +804,8 @@ func main() {
if err != nil { if err != nil {
panic(err) panic(err)
} }
}`}, 0, gosec.NewConfig()}} }`}, 0, gosec.NewConfig()},
}
// SampleCodeG201 - SQL injection via format string // SampleCodeG201 - SQL injection via format string
SampleCodeG201 = []CodeSample{ SampleCodeG201 = []CodeSample{
@ -971,7 +985,8 @@ import (
func main(){ func main(){
fmt.Sprintln() fmt.Sprintln()
}`}, 0, gosec.NewConfig()}} }`}, 0, gosec.NewConfig()},
}
// SampleCodeG202 - SQL query string building via string concatenation // SampleCodeG202 - SQL query string building via string concatenation
SampleCodeG202 = []CodeSample{ SampleCodeG202 = []CodeSample{
@ -1125,7 +1140,8 @@ func main(){
} }
defer rows.Close() defer rows.Close()
} }
`}, 0, gosec.NewConfig()}} `}, 0, gosec.NewConfig()},
}
// SampleCodeG203 - Template checks // SampleCodeG203 - Template checks
SampleCodeG203 = []CodeSample{ SampleCodeG203 = []CodeSample{
@ -1163,7 +1179,8 @@ func main() {
"Body": template.HTML(a), "Body": template.HTML(a),
} }
t.Execute(os.Stdout, v) t.Execute(os.Stdout, v)
}`}, 1, gosec.NewConfig()}, {[]string{ }`,
}, 1, gosec.NewConfig()}, {[]string{
` `
package main package main
import ( import (
@ -1179,7 +1196,8 @@ func main() {
"Body": template.JS(a), "Body": template.JS(a),
} }
t.Execute(os.Stdout, v) t.Execute(os.Stdout, v)
}`}, 1, gosec.NewConfig()}, {[]string{ }`,
}, 1, gosec.NewConfig()}, {[]string{
` `
package main package main
import ( import (
@ -1195,10 +1213,13 @@ func main() {
"Body": template.URL(a), "Body": template.URL(a),
} }
t.Execute(os.Stdout, v) t.Execute(os.Stdout, v)
}`}, 1, gosec.NewConfig()}} }`,
}, 1, gosec.NewConfig()},
}
// SampleCodeG204 - Subprocess auditing // SampleCodeG204 - Subprocess auditing
SampleCodeG204 = []CodeSample{{[]string{` SampleCodeG204 = []CodeSample{
{[]string{`
package main package main
import ( import (
"log" "log"
@ -1211,7 +1232,8 @@ func main() {
log.Fatal(err) log.Fatal(err)
} }
log.Printf("Command finished with error: %v", err) log.Printf("Command finished with error: %v", err)
}`}, 0, gosec.NewConfig()}, {[]string{` }`}, 0, gosec.NewConfig()},
{[]string{`
// Calling any function which starts a new process with using // Calling any function which starts a new process with using
// command line arguments as it's arguments is considered dangerous // command line arguments as it's arguments is considered dangerous
package main package main
@ -1227,7 +1249,8 @@ func main() {
log.Fatal(err) log.Fatal(err)
} }
log.Printf("Command finished with error: %v", err) log.Printf("Command finished with error: %v", err)
}`}, 1, gosec.NewConfig()}, {[]string{` }`}, 1, gosec.NewConfig()},
{[]string{`
// Initializing a local variable using a environmental // Initializing a local variable using a environmental
// variable is consider as a dangerous user input // variable is consider as a dangerous user input
package main package main
@ -1246,7 +1269,8 @@ func main() {
log.Printf("Waiting for command to finish...") log.Printf("Waiting for command to finish...")
err = cmd.Wait() err = cmd.Wait()
log.Printf("Command finished with error: %v", err) log.Printf("Command finished with error: %v", err)
}`}, 1, gosec.NewConfig()}, {[]string{` }`}, 1, gosec.NewConfig()},
{[]string{`
// gosec doesn't have enough context to decide that the // gosec doesn't have enough context to decide that the
// command argument of the RunCmd function is harcoded string // command argument of the RunCmd function is harcoded string
// and that's why it's better to warn the user so he can audit it // and that's why it's better to warn the user so he can audit it
@ -1269,7 +1293,8 @@ func RunCmd(command string) {
func main() { func main() {
RunCmd("sleep") RunCmd("sleep")
}`}, 1, gosec.NewConfig()}, {[]string{` }`}, 1, gosec.NewConfig()},
{[]string{`
// syscall.Exec function called with harcoded arguments // syscall.Exec function called with harcoded arguments
// shouldn't be consider as a command injection // shouldn't be consider as a command injection
package main package main
@ -1283,7 +1308,8 @@ func main() {
fmt.Printf("Error: %v\n", err) fmt.Printf("Error: %v\n", err)
} }
}`}, 0, gosec.NewConfig()}, }`}, 0, gosec.NewConfig()},
{[]string{` {
[]string{`
package main package main
import ( import (
@ -1302,7 +1328,8 @@ func main() {
RunCmd("sleep") RunCmd("sleep")
}`}, 1, gosec.NewConfig(), }`}, 1, gosec.NewConfig(),
}, },
{[]string{` {
[]string{`
package main package main
import ( import (
@ -1340,7 +1367,8 @@ func main() {
log.Printf("Waiting for command to finish...") log.Printf("Waiting for command to finish...")
err = cmd.Wait() err = cmd.Wait()
log.Printf("Command finished with error: %v", err) log.Printf("Command finished with error: %v", err)
}`}, 0, gosec.NewConfig()}} }`}, 0, gosec.NewConfig()},
}
// SampleCodeG301 - mkdir permission check // SampleCodeG301 - mkdir permission check
SampleCodeG301 = []CodeSample{{[]string{` SampleCodeG301 = []CodeSample{{[]string{`
@ -1855,7 +1883,8 @@ func main() {
w.Flush() w.Flush()
}`}, 1, gosec.NewConfig()}} }`}, 1, gosec.NewConfig()},
}
// SampleCodeG307 - Unsafe defer of os.Close // SampleCodeG307 - Unsafe defer of os.Close
SampleCodeG307 = []CodeSample{ SampleCodeG307 = []CodeSample{
{[]string{`package main {[]string{`package main
@ -1904,7 +1933,8 @@ func main() {
w.Flush() w.Flush()
}`}, 1, gosec.NewConfig()}} }`}, 1, gosec.NewConfig()},
}
// SampleCodeG401 - Use of weak crypto MD5 // SampleCodeG401 - Use of weak crypto MD5
SampleCodeG401 = []CodeSample{ SampleCodeG401 = []CodeSample{
@ -1937,7 +1967,8 @@ func main() {
log.Fatal(err) log.Fatal(err)
} }
fmt.Printf("%x", h.Sum(nil)) fmt.Printf("%x", h.Sum(nil))
}`}, 1, gosec.NewConfig()}} }`}, 1, gosec.NewConfig()},
}
// SampleCodeG401b - Use of weak crypto SHA1 // SampleCodeG401b - Use of weak crypto SHA1
SampleCodeG401b = []CodeSample{ SampleCodeG401b = []CodeSample{
@ -1962,7 +1993,8 @@ func main() {
log.Fatal(err) log.Fatal(err)
} }
fmt.Printf("%x", h.Sum(nil)) fmt.Printf("%x", h.Sum(nil))
}`}, 1, gosec.NewConfig()}} }`}, 1, gosec.NewConfig()},
}
// SampleCodeG402 - TLS settings // SampleCodeG402 - TLS settings
SampleCodeG402 = []CodeSample{{[]string{` SampleCodeG402 = []CodeSample{{[]string{`
@ -2001,7 +2033,8 @@ func main() {
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
} }
}`}, 1, gosec.NewConfig()}, {[]string{` }`,
}, 1, gosec.NewConfig()}, {[]string{`
// Insecure max version // Insecure max version
package main package main
import ( import (
@ -2040,7 +2073,8 @@ func main() {
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
} }
}`}, 1, gosec.NewConfig()}, {[]string{` }`}, 1, gosec.NewConfig(),
}, {[]string{`
// secure max version when min version is specified // secure max version when min version is specified
package main package main
import ( import (
@ -2092,7 +2126,8 @@ func main() {
fmt.Println(err) fmt.Println(err)
} }
fmt.Println(pvk) fmt.Println(pvk)
}`}, 1, gosec.NewConfig()}} }`}, 1, gosec.NewConfig()},
}
// SampleCodeG404 - weak random number // SampleCodeG404 - weak random number
SampleCodeG404 = []CodeSample{ SampleCodeG404 = []CodeSample{
@ -2140,7 +2175,8 @@ import (
func main() { func main() {
bad := rand.Intn(10) bad := rand.Intn(10)
println(bad) println(bad)
}`}, 1, gosec.NewConfig()}} }`}, 1, gosec.NewConfig()},
}
// SampleCodeG501 - Blocklisted import MD5 // SampleCodeG501 - Blocklisted import MD5
SampleCodeG501 = []CodeSample{ SampleCodeG501 = []CodeSample{
@ -2155,7 +2191,8 @@ func main() {
for _, arg := range os.Args { for _, arg := range os.Args {
fmt.Printf("%x - %s\n", md5.Sum([]byte(arg)), arg) fmt.Printf("%x - %s\n", md5.Sum([]byte(arg)), arg)
} }
}`}, 1, gosec.NewConfig()}} }`}, 1, gosec.NewConfig()},
}
// SampleCodeG502 - Blocklisted import DES // SampleCodeG502 - Blocklisted import DES
SampleCodeG502 = []CodeSample{ SampleCodeG502 = []CodeSample{
@ -2183,7 +2220,8 @@ func main() {
stream := cipher.NewCFBEncrypter(block, iv) stream := cipher.NewCFBEncrypter(block, iv)
stream.XORKeyStream(ciphertext[des.BlockSize:], plaintext) stream.XORKeyStream(ciphertext[des.BlockSize:], plaintext)
fmt.Println("Secret message is: %s", hex.EncodeToString(ciphertext)) fmt.Println("Secret message is: %s", hex.EncodeToString(ciphertext))
}`}, 1, gosec.NewConfig()}} }`}, 1, gosec.NewConfig()},
}
// SampleCodeG503 - Blocklisted import RC4 // SampleCodeG503 - Blocklisted import RC4
SampleCodeG503 = []CodeSample{{[]string{` SampleCodeG503 = []CodeSample{{[]string{`
@ -2227,11 +2265,13 @@ func main() {
for _, arg := range os.Args { for _, arg := range os.Args {
fmt.Printf("%x - %s\n", sha1.Sum([]byte(arg)), arg) fmt.Printf("%x - %s\n", sha1.Sum([]byte(arg)), arg)
} }
}`}, 1, gosec.NewConfig()}} }`}, 1, gosec.NewConfig()},
}
// SampleCodeG601 - Implicit aliasing over range statement // SampleCodeG601 - Implicit aliasing over range statement
SampleCodeG601 = []CodeSample{ SampleCodeG601 = []CodeSample{
{[]string{` {[]string{
`
package main package main
import "fmt" import "fmt"