Compare commits

...

36 Commits

Author SHA1 Message Date
Cosmin Cojocar
00bbbd8413 Fix the release workflow to allow unsecure commands
Signed-off-by: Cosmin Cojocar <ccojocar@cloudbees.com>
2021-01-22 11:36:52 +01:00
Mark Wolfe
d9d75834b6 update README with instructions on how to integrate with GitHub codescanning 2021-01-22 11:31:07 +01:00
Mark Wolfe
3ed39fe612 fix sarif add default configuration set to correct level 2021-01-22 10:26:59 +01:00
Mark Wolfe
732f759e4f fix for sarif which maps level from issue severity 2021-01-21 18:26:43 +01:00
Mark Wolfe
327b2a0841 ensure the sarif results are an empty array if nothing is reported 2021-01-21 11:03:13 +01:00
K
41ea431779 Fix for SARIF output when Issue.Line contains a range 2021-01-05 08:38:25 +01:00
Cosmin Cojocar
a5911ad7bb Fix compilation errors in the test samples
Signed-off-by: Cosmin Cojocar <ccojocar@cloudbees.com>
2021-01-04 09:28:00 +01:00
Chris Bandy
23ef7009f9 Fix some typos in rules tests 2021-01-04 09:28:00 +01:00
Chris Bandy
e100f6b862 Assert that sample code compiles 2021-01-04 09:28:00 +01:00
Cosmin Cojocar
bcfb27955e Clean up the go module dependncies (#555)
* Clean up the dependencies

Signed-off-by: Cosmin Cojocar <ccojocar@cloudbees.com>

* Add pq package to dependencies
2021-01-04 08:41:45 +01:00
renovate[bot]
e4d0e9f5be Update all dependencies (#553)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-01-04 08:03:52 +01:00
Jeff Widman
9fe0b2e21a Fix typo (#547) 2020-12-11 09:34:38 +01:00
renovate[bot]
d8fa95aad8 Update all dependencies (#544)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2020-12-01 09:29:25 +01:00
Ethan Buchman
984c1d39a0 fix typo in ContainsPkgCallExpr comment (#545) 2020-12-01 09:28:38 +01:00
renovate[bot]
208b73eec4 Update all dependencies (#538)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2020-11-02 09:15:56 +01:00
mrtc0
0d4f1cb2cb Support SARIF output (#539)
* SARIF support

* add sarif option to help text
2020-11-02 09:13:53 +01:00
renovate[bot]
a4746e18e3 Update all dependencies (#533)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2020-10-07 20:32:18 +02:00
Miki Tebeka
6bd6e4ba2c Use $(go env GOPATH) that works even when GOPATH is not set 2020-10-01 04:17:43 +10:00
Lucas Charles
aef335a98e Fix typo in README.md
s/trucate/truncate for G101 configuration
2020-10-01 04:17:00 +10:00
xpivarc
0ce48a584f Reproducible junit report (#529)
* Fix junit format ordering

Signed-off-by: L. Pivarc <lpivarc@redhat.com>

* Make ordering stable

Signed-off-by: L. Pivarc <lpivarc@redhat.com>

* Test ordering

Signed-off-by: L. Pivarc <lpivarc@redhat.com>
2020-09-29 19:17:38 +02:00
Cosmin Cojocar
868556b846 Update README with the correct path to tlsconfig command
Signed-off-by: Cosmin Cojocar <ccojocar@cloudbees.com>
2020-09-03 10:54:08 +02:00
Cosmin Cojocar
13519fda59 Update the tls configuration generate to handle also the NSS alternative names
Regenerate the configuration of TLS rule.

Signed-off-by: Cosmin Cojocar <ccojocar@cloudbees.com>
2020-09-03 10:54:08 +02:00
Renovate Bot
e351067255 Update all dependencies 2020-09-01 08:58:31 +02:00
Cosmin Cojocar
166e4f5f45 Update README file with some more details required to run successfully a scan with the docker image
The current working directory needs to be specified in the docker run option in order for gosec
to download the dependencies defined in the go module file.

Signed-off-by: Cosmin Cojocar <ccojocar@cloudbees.com>
2020-09-01 08:57:52 +02:00
Cosmin Cojocar
f5cc32a320 Update the Go version to 1.15 in the Makefile
This is only used when building locally the docker image.

Signed-off-by: Cosmin Cojocar <ccojocar@cloudbees.com>
2020-09-01 08:57:52 +02:00
Cosmin Cojocar
ea0fa28b7f Update the Github go action version to 1.6.0
Signed-off-by: Cosmin Cojocar <ccojocar@cloudbees.com>
2020-08-31 10:27:23 +02:00
Cosmin Cojocar
feea8bb243 Fix the action tag
Signed-off-by: Cosmin Cojocar <ccojocar@cloudbees.com>
2020-08-31 10:27:23 +02:00
Cosmin Cojocar
6688a97661 Fix the github action for Go 1.15
Signed-off-by: Cosmin Cojocar <ccojocar@cloudbees.com>
2020-08-31 10:27:23 +02:00
Cosmin Cojocar
7234349e33 Add Go 1.15 to the supported version and phase out the Go 1.12
Also updated the release automation to release gosec with use Go 1.15

Signed-off-by: Cosmin Cojocar <ccojocar@cloudbees.com>
2020-08-31 10:27:23 +02:00
Cosmin Cojocar
a3895d5c55 Fix typo in README file
Signed-off-by: Cosmin Cojocar <ccojocar@cloudbees.com>
2020-08-31 10:27:02 +02:00
Jamie Cuthill
17c955519e Incorrect local installation instructions for v2 2020-08-21 11:23:36 +02:00
Cosmin Cojocar
f13b8bc639 Add also filepath.Rel as a sanitization method for input argument in the G304 rule
Signed-off-by: Cosmin Cojocar <ccojocar@cloudbees.com>
2020-08-19 09:40:07 +02:00
Cosmin Cojocar
047729a84f Fix the rule G304 to handle the case when the input is cleaned as a variable assignment
Signed-off-by: Cosmin Cojocar <ccojocar@cloudbees.com>
2020-08-19 09:40:07 +02:00
ggkitsas
b60ddc21ba feat: adds support for path.Join and for tar archives in G305 2020-08-03 09:17:45 +02:00
Renovate Bot
673a139e55 Update all dependencies 2020-08-03 09:07:46 +02:00
Cosmin Cojocar
110b62b05f Add io.CopyBuffer function to rule G110
Signed-off-by: Cosmin Cojocar <cosmin.cojocar@gmx.ch>
2020-07-29 14:25:45 +02:00
23 changed files with 742 additions and 119 deletions

View File

@@ -7,6 +7,17 @@ on:
branches:
- master
jobs:
tests-go-1-15:
runs-on: ubuntu-latest
env:
GO111MODULE: on
steps:
- name: Checkout Source
uses: actions/checkout@v2
- name: Run Tests
uses: cedrickring/golang-action@1.6.0
with:
args: make test
tests-go-1-14:
runs-on: ubuntu-latest
env:
@@ -15,7 +26,7 @@ jobs:
- name: Checkout Source
uses: actions/checkout@v2
- name: Run Tests
uses: cedrickring/golang-action@1.5.1
uses: cedrickring/golang-action/go1.14@1.6.0
with:
args: make test
tests-go-1-13:
@@ -26,22 +37,11 @@ jobs:
- name: Checkout Source
uses: actions/checkout@v2
- name: Run Tests
uses: cedrickring/golang-action/go1.13@1.5.1
with:
args: make test
tests-go-1-12:
runs-on: ubuntu-latest
env:
GO111MODULE: on
steps:
- name: Checkout Source
uses: actions/checkout@v2
- name: Run Tests
uses: cedrickring/golang-action/go1.12@1.5.1
uses: cedrickring/golang-action/go1.13@1.6.0
with:
args: make test
coverage:
needs: [tests-go-1-14, tests-go-1-13, tests-go-1-12]
needs: [tests-go-1-15, tests-go-1-14, tests-go-1-13]
runs-on: ubuntu-latest
env:
GO111MODULE: on
@@ -49,7 +49,7 @@ jobs:
- name: Checkout Source
uses: actions/checkout@v2
- name: Create Test Coverage
uses: cedrickring/golang-action@1.5.1
uses: cedrickring/golang-action@1.6.0
with:
args: make test-coverage
- name: Upload Test Coverage

View File

@@ -8,20 +8,21 @@ jobs:
runs-on: ubuntu-latest
env:
GO111MODULE: on
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
steps:
- name: Checkout Source
uses: actions/checkout@v2
- name: Unshallow
run: git fetch --prune --unshallow
- name: Set up Go
uses: actions/setup-go@v1
uses: actions/setup-go@v2
with:
go-version: 1.14.x
go-version: 1.15.x
- name : Get release version
id: get_version
run: echo ::set-env name=RELEASE_VERSION::$(echo ${GITHUB_REF:10})
- name: Release Binaries
uses: goreleaser/goreleaser-action@v1
uses: goreleaser/goreleaser-action@v2
with:
version: latest
args: release --rm-dist
@@ -33,6 +34,6 @@ jobs:
name: securego/gosec
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
buildargs: GO_VERSION=1.14
buildargs: GO_VERSION=1.15
tags: "latest,${{ env.RELEASE_VERSION }}"
tag_names: true

View File

@@ -11,7 +11,7 @@ GOBIN ?= $(GOPATH)/bin
GOLINT ?= $(GOBIN)/golint
GOSEC ?= $(GOBIN)/gosec
GINKGO ?= $(GOBIN)/ginkgo
GO_VERSION = 1.14
GO_VERSION = 1.15
default:
$(MAKE) build

View File

@@ -28,8 +28,8 @@ You may obtain a copy of the License [here](http://www.apache.org/licenses/LICEN
### CI Installation
```bash
# binary will be $GOPATH/bin/gosec
curl -sfL https://raw.githubusercontent.com/securego/gosec/master/install.sh | sh -s -- -b $GOPATH/bin vX.Y.Z
# binary will be $(go env GOPATH)/bin/gosec
curl -sfL https://raw.githubusercontent.com/securego/gosec/master/install.sh | sh -s -- -b $(go env GOPATH)/bin vX.Y.Z
# or install it into ./bin/
curl -sfL https://raw.githubusercontent.com/securego/gosec/master/install.sh | sh -s vX.Y.Z
@@ -74,10 +74,46 @@ jobs:
args: ./...
```
### Integrating with code scanning
You can [integrate third-party code analysis tools](https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/integrating-with-code-scanning) with GitHub code scanning by uploading data as SARIF files.
The workflow shows an example of running the `gosec` as a step in a GitHub action workflow which outputs the `results.sarif` file. The workflow then uploads the `results.sarif` file to GitHub using the `upload-sarif` action.
```yaml
name: "Security Scan"
# Run workflow each time code is pushed to your repository and on a schedule.
# The scheduled workflow runs every at 00:00 on Sunday UTC time.
on:
push:
schedule:
- cron: '0 0 * * 0'
jobs:
tests:
runs-on: ubuntu-latest
env:
GO111MODULE: on
steps:
- name: Checkout Source
uses: actions/checkout@v2
- name: Run Gosec Security Scanner
uses: securego/gosec@master
with:
# we let the report trigger content trigger a failure using the GitHub Security features.
args: '-no-fail -fmt sarif -out results.sarif ./...'
- name: Upload SARIF file
uses: github/codeql-action/upload-sarif@v1
with:
# Path to SARIF file relative to the root of the repository
sarif_file: results.sarif
```
### Local Installation
```bash
go get github.com/securego/gosec/cmd/gosec
go get github.com/securego/gosec/v2/cmd/gosec
```
## Usage
@@ -107,7 +143,7 @@ directory you can supply `./...` as the input argument.
- G302: Poor file permissions used with chmod
- G303: Creating tempfile using a predictable path
- G304: File path provided as taint input
- G305: File traversal when extracting zip archive
- G305: File traversal when extracting zip/tar archive
- G306: Poor file permissions used when writing to a new file
- G307: Deferring a method which returns an error
- G401: Detect the usage of DES, RC4, MD5 or SHA1
@@ -178,10 +214,10 @@ You can also configure the hard-coded credentials rule `G101` with additional pa
{
"G101": {
"pattern": "(?i)passwd|pass|password|pwd|secret|private_key|token",
"ingnore_entropy": false,
"ignore_entropy": false,
"entropy_threshold": "80.0",
"per_char_threshold": "3.0",
"trucate": "32"
"truncate": "32"
}
}
```
@@ -304,8 +340,9 @@ You can run the `gosec` tool in a container against your local Go project. You o
into a volume as follows:
```bash
docker run -it -v <YOUR PROJECT PATH>/<PROJECT>:/<PROJECT> securego/gosec /<PROJECT>/...
docker run --rm -it -w /<PROJECT>/ -v <YOUR PROJECT PATH>/<PROJECT>:/<PROJECT> securego/gosec /<PROJECT>/...
```
**Note:** the current working directory needs to be set with `-w` option in order to get successfully resolved the dependencies from go module file
### Generate TLS rule
@@ -314,7 +351,7 @@ The configuration of TLS rule can be generated from [Mozilla's TLS ciphers recom
First you need to install the generator tool:
```bash
go get github.com/securego/gosec/cmd/tlsconfig/...
go get github.com/securego/gosec/v2/cmd/tlsconfig/...
```
You can invoke now the `go generate` in the root of the project:

View File

@@ -70,7 +70,7 @@ func (c CallList) ContainsPointer(selector, indent string) bool {
}
// ContainsPkgCallExpr resolves the call expression name and type, and then further looks
// up the package path for that type. Finally, it determines if the call exists within the call list
// up the package path for that type. Finally, it determines if the call exists within the call list
func (c CallList) ContainsPkgCallExpr(n ast.Node, ctx *Context, stripVendor bool) *ast.CallExpr {
selector, ident, err := GetCallInfo(n, ctx)
if err != nil {

View File

@@ -73,7 +73,7 @@ var (
flagIgnoreNoSec = flag.Bool("nosec", false, "Ignores #nosec comments when set")
// format output
flagFormat = flag.String("fmt", "text", "Set output format. Valid options are: json, yaml, csv, junit-xml, html, sonarqube, golint or text")
flagFormat = flag.String("fmt", "text", "Set output format. Valid options are: json, yaml, csv, junit-xml, html, sonarqube, golint, sarif or text")
// #nosec alternative tag
flagAlternativeNoSec = flag.String("nosec-tag", "", "Set an alternative string for #nosec. Some examples: #dontanalyze, #falsepositive")

View File

@@ -2,15 +2,35 @@ package main
import (
"sort"
"strconv"
"strings"
"github.com/securego/gosec/v2"
)
// handle ranges
func extractLineNumber(s string) int {
lineNumber, _ := strconv.Atoi(strings.Split(s, "-")[0])
return lineNumber
}
type sortBySeverity []*gosec.Issue
func (s sortBySeverity) Len() int { return len(s) }
func (s sortBySeverity) Less(i, j int) bool { return s[i].Severity > s[j].Severity }
func (s sortBySeverity) Less(i, j int) bool {
if s[i].Severity == s[j].Severity {
if s[i].What == s[j].What {
if s[i].File == s[j].File {
return extractLineNumber(s[i].Line) > extractLineNumber(s[j].Line)
}
return s[i].File > s[j].File
}
return s[i].What > s[j].What
}
return s[i].Severity > s[j].Severity
}
func (s sortBySeverity) Swap(i, j int) { s[i], s[j] = s[j], s[i] }

View File

@@ -0,0 +1,80 @@
package main
import (
"testing"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/securego/gosec/v2"
)
var defaultIssue = gosec.Issue{
File: "/home/src/project/test.go",
Line: "1",
Col: "1",
RuleID: "ruleID",
What: "test",
Confidence: gosec.High,
Severity: gosec.High,
Code: "1: testcode",
Cwe: gosec.GetCwe("G101"),
}
func createIssue() gosec.Issue {
return defaultIssue
}
func TestRules(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Sort issues Suite")
}
func firstIsGreater(less, greater *gosec.Issue) {
slice := []*gosec.Issue{less, greater}
sortIssues(slice)
ExpectWithOffset(0, slice[0]).To(Equal(greater))
}
var _ = Describe("Sorting by Severity", func() {
It("sortes by severity", func() {
less := createIssue()
less.Severity = gosec.Low
greater := createIssue()
less.Severity = gosec.High
firstIsGreater(&less, &greater)
})
Context("Serverity is same", func() {
It("sortes by What", func() {
less := createIssue()
less.What = "test1"
greater := createIssue()
greater.What = "test2"
firstIsGreater(&less, &greater)
})
})
Context("Serverity and What is same", func() {
It("sortes by File", func() {
less := createIssue()
less.File = "test1"
greater := createIssue()
greater.File = "test2"
firstIsGreater(&less, &greater)
})
})
Context("Serverity, What and File is same", func() {
It("sortes by line number", func() {
less := createIssue()
less.Line = "1"
greater := createIssue()
greater.Line = "2"
firstIsGreater(&less, &greater)
})
})
})

View File

@@ -97,6 +97,9 @@ func getGoCipherConfig(name string, sstls ServerSideTLSJson) (goCipherConfigurat
}
if len(cipherSuite.IANAName) > 0 {
cipherConf.Ciphers = append(cipherConf.Ciphers, cipherSuite.IANAName)
if len(cipherSuite.NSSName) > 0 && cipherSuite.NSSName != cipherSuite.IANAName {
cipherConf.Ciphers = append(cipherConf.Ciphers, cipherSuite.NSSName)
}
}
}

16
go.mod
View File

@@ -2,17 +2,17 @@ module github.com/securego/gosec/v2
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/gookit/color v1.2.5
github.com/gookit/color v1.3.6
github.com/kr/pretty v0.1.0 // indirect
github.com/mozilla/tls-observatory v0.0.0-20200317151703-4fa42e1c2dee
github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d
github.com/onsi/ginkgo v1.13.0
github.com/onsi/gomega v1.10.1
github.com/lib/pq v1.9.0 // indirect
github.com/mozilla/tls-observatory v0.0.0-20201209171846-0547674fceff
github.com/nbutton23/zxcvbn-go v0.0.0-20201221231540-e56b841a3c88
github.com/onsi/ginkgo v1.14.2
github.com/onsi/gomega v1.10.4
github.com/stretchr/testify v1.4.0 // indirect
golang.org/x/text v0.3.2 // indirect
golang.org/x/tools v0.0.0-20200701041122-1837592efa10
golang.org/x/tools v0.0.0-20210102185154-773b96fafca2
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
gopkg.in/yaml.v2 v2.3.0
gopkg.in/yaml.v2 v2.4.0
)
go 1.14

70
go.sum
View File

@@ -3,24 +3,23 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/gookit/color v1.2.4 h1:xOYBan3Fwlrqj1M1UN2TlHOCRiek3bGzWf/vPnJ1roE=
github.com/gookit/color v1.2.4/go.mod h1:AhIE+pS6D4Ql0SQWbBeXPHw7gY0/sjHoA4s/n1KB7xg=
github.com/gookit/color v1.2.5 h1:s1gzb/fg3HhkSLKyWVUsZcVBUo+R1TwEYTmmxH8gGFg=
github.com/gookit/color v1.2.5/go.mod h1:AhIE+pS6D4Ql0SQWbBeXPHw7gY0/sjHoA4s/n1KB7xg=
github.com/gookit/color v1.3.6 h1:Rgbazd4JO5AgSTVGS3o0nvaSdwdrS8bzvIXwtK6OiMk=
github.com/gookit/color v1.3.6/go.mod h1:R3ogXq2B9rTbXoSHJ1HyUVAZ3poOJHpd9nQmyGZsfvQ=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
@@ -28,46 +27,51 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mozilla/tls-observatory v0.0.0-20200317151703-4fa42e1c2dee h1:1xJ+Xi9lYWLaaP4yB67ah0+548CD3110mCPWhVVjFkI=
github.com/mozilla/tls-observatory v0.0.0-20200317151703-4fa42e1c2dee/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk=
github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d h1:AREM5mwr4u1ORQBMvzfzBgpsctsbQikCVpvC+tX285E=
github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU=
github.com/lib/pq v1.9.0 h1:L8nSXQQzAYByakOFMTwpjRoHsMJklur4Gi59b6VivR8=
github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/mozilla/tls-observatory v0.0.0-20201209171846-0547674fceff h1:1l3C92dKs28p0T3Abeem2JDPbtQgEWyNVzflHmyrAwU=
github.com/mozilla/tls-observatory v0.0.0-20201209171846-0547674fceff/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk=
github.com/nbutton23/zxcvbn-go v0.0.0-20201221231540-e56b841a3c88 h1:o+O3Cd1HO9CTgxE3/C8p5I5Y4C0yYWbF8d4IkfOLtcQ=
github.com/nbutton23/zxcvbn-go v0.0.0-20201221231540-e56b841a3c88/go.mod h1:KSVJerMDfblTH7p5MZaTt+8zaT2iEk3AkVb9PQdZuE8=
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.0 h1:Iw5WCbBcaAAd0fpRb1c9r5YCylv4XDoCSigm1zLevwU=
github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.12.3/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
github.com/onsi/ginkgo v1.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1lskyM0=
github.com/onsi/ginkgo v1.14.2 h1:8mVmC9kjFFmA8H4pKMUhcblgifdkOIXPvbhN1T36q1M=
github.com/onsi/ginkgo v1.14.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
github.com/onsi/gomega v1.7.1 h1:K0jcRCwNQM3vFGh1ppMtDh/+7ApJrjldlX8fA0jDTLQ=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.9.0 h1:R1uwffexN6Pr340GtYRIdZmAiN4J+iw6WG4wog1DUXg=
github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.10.4 h1:NiTx7EEvBzu9sFOD1zORteLSt3o8gnlvZZwSE9TnY9U=
github.com/onsi/gomega v1.10.4/go.mod h1:g/HbgYopi++010VEqkFgJHKC09uJiW9UkXvMUuKHUCQ=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.1.4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b h1:0mm1VjtFUOIlE1SbDlwjYaDxZVDP2S5ou6y0gSgXHu8=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb h1:eBmm0M9fYhWpKZLjQUUKka/LtIxf46G4fxeEz5KJr9U=
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -76,29 +80,33 @@ golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e h1:N7DeIrjYszNmSW409R3frPPwglRwMkXSBzwVbkOjLLA=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299 h1:DYfZAGf2WMFjMxbgTjaC+2HC7NkNAQs+6Q8b9WEB/F4=
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200331202046-9d5940d49312 h1:2PHG+Ia3gK1K2kjxZnSylizb//eyaMG8gDFbOG7wLV8=
golang.org/x/tools v0.0.0-20200331202046-9d5940d49312/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200601175630-2caf76543d99 h1:deddXmhOJb/bvD/4M/j2AUMrhHeh6GkqykJSCWyTNVk=
golang.org/x/tools v0.0.0-20200601175630-2caf76543d99/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200701041122-1837592efa10 h1:/dVa/Kj8QBudsXg83xokTMENAVrcMqZdhECHe1y2LJ0=
golang.org/x/tools v0.0.0-20200701041122-1837592efa10/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210102185154-773b96fafca2 h1:crjwvdT+rSAILpNOKhk/BNmefsucqGTeeRX2YBK/6Jg=
golang.org/x/tools v0.0.0-20210102185154-773b96fafca2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
@@ -111,7 +119,7 @@ gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=

View File

@@ -48,6 +48,9 @@ const (
// ReportJUnitXML set the output format to junit xml
ReportJUnitXML // JUnit XML format
// ReportSARIF set the output format to SARIF
ReportSARIF // SARIF format
//SonarqubeEffortMinutes effort to fix in minutes
SonarqubeEffortMinutes = 5
)
@@ -108,6 +111,8 @@ func CreateReport(w io.Writer, format string, enableColor bool, rootPaths []stri
err = reportSonarqube(rootPaths, w, data)
case "golint":
err = reportGolint(w, data)
case "sarif":
err = reportSARIFTemplate(rootPaths, w, data)
default:
err = reportFromPlaintextTemplate(w, text, enableColor, data)
}
@@ -172,6 +177,53 @@ func convertToSonarIssues(rootPaths []string, data *reportInfo) (*sonarIssues, e
return si, nil
}
func convertToSarifReport(rootPaths []string, data *reportInfo) (*sarifReport, error) {
sr := buildSarifReport()
var rules []*sarifRule
var locations []*sarifLocation
results := []*sarifResult{}
for index, issue := range data.Issues {
rules = append(rules, buildSarifRule(issue))
location, err := buildSarifLocation(issue, rootPaths)
if err != nil {
return nil, err
}
locations = append(locations, location)
result := &sarifResult{
RuleID: fmt.Sprintf("%s (CWE-%s)", issue.RuleID, issue.Cwe.ID),
RuleIndex: index,
Level: getSarifLevel(issue.Severity.String()),
Message: &sarifMessage{
Text: issue.What,
},
Locations: locations,
}
results = append(results, result)
}
tool := &sarifTool{
Driver: &sarifDriver{
Name: "gosec",
InformationURI: "https://github.com/securego/gosec/",
Rules: rules,
},
}
run := &sarifRun{
Tool: tool,
Results: results,
}
sr.Runs = append(sr.Runs, run)
return sr, nil
}
func reportJSON(w io.Writer, data *reportInfo) error {
raw, err := json.MarshalIndent(data, "", "\t")
if err != nil {
@@ -242,9 +294,7 @@ func reportGolint(w io.Writer, data *reportInfo) error {
}
func reportJUnitXML(w io.Writer, data *reportInfo) error {
groupedData := groupDataByRules(data)
junitXMLStruct := createJUnitXMLStruct(groupedData)
junitXMLStruct := createJUnitXMLStruct(data)
raw, err := xml.MarshalIndent(junitXMLStruct, "", "\t")
if err != nil {
return err
@@ -260,6 +310,20 @@ func reportJUnitXML(w io.Writer, data *reportInfo) error {
return nil
}
func reportSARIFTemplate(rootPaths []string, w io.Writer, data *reportInfo) error {
sr, err := convertToSarifReport(rootPaths, data)
if err != nil {
return err
}
raw, err := json.MarshalIndent(sr, "", "\t")
if err != nil {
return err
}
_, err = w.Write(raw)
return err
}
func reportFromPlaintextTemplate(w io.Writer, reportTemplate string, enableColor bool, data *reportInfo) error {
t, e := plainTemplate.
New("gosec").

View File

@@ -12,6 +12,13 @@ import (
"gopkg.in/yaml.v2"
)
func createIssueWithFileWhat(file, what string) *gosec.Issue {
issue := createIssue("i1", gosec.GetCwe("G101"))
issue.File = file
issue.What = what
return &issue
}
func createIssue(ruleID string, cwe gosec.Cwe) gosec.Issue {
return gosec.Issue{
File: "/home/src/project/test.go",
@@ -248,6 +255,23 @@ var _ = Describe("Formatter", func() {
Expect(*issues).To(Equal(*want))
})
})
Context("When using junit", func() {
It("preserves order of issues", func() {
issues := []*gosec.Issue{createIssueWithFileWhat("i1", "1"), createIssueWithFileWhat("i2", "2"), createIssueWithFileWhat("i3", "1")}
junitReport := createJUnitXMLStruct(&reportInfo{Issues: issues})
testSuite := junitReport.Testsuites[0]
Expect(testSuite.Testcases[0].Name).To(Equal(issues[0].File))
Expect(testSuite.Testcases[1].Name).To(Equal(issues[2].File))
testSuite = junitReport.Testsuites[1]
Expect(testSuite.Testcases[0].Name).To(Equal(issues[1].File))
})
})
Context("When using different report formats", func() {
grules := []string{"G101", "G102", "G103", "G104", "G106",
@@ -417,5 +441,24 @@ var _ = Describe("Formatter", func() {
Expect(string(buf.String())).To(Equal(expect))
}
})
It("sarif formatted report should contain the CWE mapping", func() {
for _, rule := range grules {
cwe := gosec.IssueToCWE[rule]
issue := createIssue(rule, cwe)
error := map[string][]gosec.Error{}
buf := new(bytes.Buffer)
err := CreateReport(buf, "sarif", false, []string{}, []*gosec.Issue{&issue}, &gosec.Metrics{}, error)
Expect(err).ShouldNot(HaveOccurred())
result := stripString(buf.String())
pattern := "rules\":[{\"id\":\"%s(CWE-%s)\""
expect := fmt.Sprintf(pattern, rule, cwe.ID)
Expect(err).ShouldNot(HaveOccurred())
Expect(result).To(ContainSubstring(expect))
}
})
})
})

View File

@@ -40,35 +40,30 @@ func generatePlaintext(issue *gosec.Issue) string {
", CWE: " + issue.Cwe.ID + ")\n" + "> " + htmlLib.EscapeString(issue.Code)
}
func groupDataByRules(data *reportInfo) map[string][]*gosec.Issue {
groupedData := make(map[string][]*gosec.Issue)
for _, issue := range data.Issues {
if _, ok := groupedData[issue.What]; !ok {
groupedData[issue.What] = []*gosec.Issue{}
}
groupedData[issue.What] = append(groupedData[issue.What], issue)
}
return groupedData
}
func createJUnitXMLStruct(groupedData map[string][]*gosec.Issue) junitXMLReport {
func createJUnitXMLStruct(data *reportInfo) junitXMLReport {
var xmlReport junitXMLReport
for what, issues := range groupedData {
testsuite := testsuite{
Name: what,
Tests: len(issues),
testsuites := map[string]int{}
for _, issue := range data.Issues {
index, ok := testsuites[issue.What]
if !ok {
xmlReport.Testsuites = append(xmlReport.Testsuites, testsuite{
Name: issue.What,
})
index = len(xmlReport.Testsuites) - 1
testsuites[issue.What] = index
}
for _, issue := range issues {
testcase := testcase{
Name: issue.File,
Failure: failure{
Message: "Found 1 vulnerability. See stacktrace for details.",
Text: generatePlaintext(issue),
},
}
testsuite.Testcases = append(testsuite.Testcases, testcase)
testcase := testcase{
Name: issue.File,
Failure: failure{
Message: "Found 1 vulnerability. See stacktrace for details.",
Text: generatePlaintext(issue),
},
}
xmlReport.Testsuites = append(xmlReport.Testsuites, testsuite)
xmlReport.Testsuites[index].Testcases = append(xmlReport.Testsuites[index].Testcases, testcase)
xmlReport.Testsuites[index].Tests++
}
return xmlReport
}

182
output/sarif_format.go Normal file
View File

@@ -0,0 +1,182 @@
package output
import (
"fmt"
"github.com/securego/gosec/v2"
"strconv"
"strings"
)
type sarifLevel string
const (
sarifNone = sarifLevel("none")
sarifNote = sarifLevel("note")
sarifWarning = sarifLevel("warning")
sarifError = sarifLevel("error")
)
type sarifProperties struct {
Tags []string `json:"tags"`
}
type sarifRule struct {
ID string `json:"id"`
Name string `json:"name"`
ShortDescription *sarifMessage `json:"shortDescription"`
FullDescription *sarifMessage `json:"fullDescription"`
Help *sarifMessage `json:"help"`
Properties *sarifProperties `json:"properties"`
DefaultConfiguration *sarifConfiguration `json:"defaultConfiguration"`
}
type sarifConfiguration struct {
Level sarifLevel `json:"level"`
}
type sarifArtifactLocation struct {
URI string `json:"uri"`
}
type sarifRegion struct {
StartLine uint64 `json:"startLine"`
EndLine uint64 `json:"endLine"`
StartColumn uint64 `json:"startColumn"`
EndColumn uint64 `json:"endColumn"`
}
type sarifPhysicalLocation struct {
ArtifactLocation *sarifArtifactLocation `json:"artifactLocation"`
Region *sarifRegion `json:"region"`
}
type sarifLocation struct {
PhysicalLocation *sarifPhysicalLocation `json:"physicalLocation"`
}
type sarifMessage struct {
Text string `json:"text"`
}
type sarifResult struct {
RuleID string `json:"ruleId"`
RuleIndex int `json:"ruleIndex"`
Level sarifLevel `json:"level"`
Message *sarifMessage `json:"message"`
Locations []*sarifLocation `json:"locations"`
}
type sarifDriver struct {
Name string `json:"name"`
InformationURI string `json:"informationUri"`
Rules []*sarifRule `json:"rules,omitempty"`
}
type sarifTool struct {
Driver *sarifDriver `json:"driver"`
}
type sarifRun struct {
Tool *sarifTool `json:"tool"`
Results []*sarifResult `json:"results"`
}
type sarifReport struct {
Schema string `json:"$schema"`
Version string `json:"version"`
Runs []*sarifRun `json:"runs"`
}
// buildSarifReport return SARIF report struct
func buildSarifReport() *sarifReport {
return &sarifReport{
Version: "2.1.0",
Schema: "https://schemastore.azurewebsites.net/schemas/json/sarif-2.1.0-rtm.4.json",
Runs: []*sarifRun{},
}
}
// buildSarifRule return SARIF rule field struct
func buildSarifRule(issue *gosec.Issue) *sarifRule {
return &sarifRule{
ID: fmt.Sprintf("%s (CWE-%s)", issue.RuleID, issue.Cwe.ID),
Name: issue.What,
ShortDescription: &sarifMessage{
Text: issue.What,
},
FullDescription: &sarifMessage{
Text: issue.What,
},
Help: &sarifMessage{
Text: fmt.Sprintf("%s\nSeverity: %s\nConfidence: %s\nCWE: %s", issue.What, issue.Severity.String(), issue.Confidence.String(), issue.Cwe.URL),
},
Properties: &sarifProperties{
Tags: []string{fmt.Sprintf("CWE-%s", issue.Cwe.ID), issue.Severity.String()},
},
DefaultConfiguration: &sarifConfiguration{
Level: getSarifLevel(issue.Severity.String()),
},
}
}
// buildSarifLocation return SARIF location struct
func buildSarifLocation(issue *gosec.Issue, rootPaths []string) (*sarifLocation, error) {
var filePath string
lines := strings.Split(issue.Line, "-")
startLine, err := strconv.ParseUint(lines[0], 10, 64)
if err != nil {
return nil, err
}
endLine := startLine
if len(lines) > 1 {
endLine, err = strconv.ParseUint(lines[1], 10, 64)
if err != nil {
return nil, err
}
}
col, err := strconv.ParseUint(issue.Col, 10, 64)
if err != nil {
return nil, err
}
for _, rootPath := range rootPaths {
if strings.HasPrefix(issue.File, rootPath) {
filePath = strings.Replace(issue.File, rootPath+"/", "", 1)
}
}
location := &sarifLocation{
PhysicalLocation: &sarifPhysicalLocation{
ArtifactLocation: &sarifArtifactLocation{
URI: filePath,
},
Region: &sarifRegion{
StartLine: startLine,
EndLine: endLine,
StartColumn: col,
EndColumn: col,
},
},
}
return location, nil
}
// From https://docs.oasis-open.org/sarif/sarif/v2.0/csprd02/sarif-v2.0-csprd02.html#_Toc10127839
// * "warning": The rule specified by ruleId was evaluated and a problem was found.
// * "error": The rule specified by ruleId was evaluated and a serious problem was found.
// * "note": The rule specified by ruleId was evaluated and a minor problem or an opportunity to improve the code was found.
func getSarifLevel(s string) sarifLevel {
switch s {
case "LOW":
return sarifWarning
case "MEDIUM":
return sarifError
case "HIGH":
return sarifError
default:
return sarifNote
}
}

View File

@@ -9,15 +9,15 @@ import (
type archive struct {
gosec.MetaData
calls gosec.CallList
argType string
calls gosec.CallList
argTypes []string
}
func (a *archive) ID() string {
return a.MetaData.ID
}
// Match inspects AST nodes to determine if the filepath.Joins uses any argument derived from type zip.File
// Match inspects AST nodes to determine if the filepath.Joins uses any argument derived from type zip.File or tar.Header
func (a *archive) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
if node := a.calls.ContainsPkgCallExpr(n, c, false); node != nil {
for _, arg := range node.Args {
@@ -35,26 +35,31 @@ func (a *archive) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
}
}
if argType != nil && argType.String() == a.argType {
return gosec.NewIssue(c, n, a.ID(), a.What, a.Severity, a.Confidence), nil
if argType != nil {
for _, t := range a.argTypes {
if argType.String() == t {
return gosec.NewIssue(c, n, a.ID(), a.What, a.Severity, a.Confidence), nil
}
}
}
}
}
return nil, nil
}
// NewArchive creates a new rule which detects the file traversal when extracting zip archives
// NewArchive creates a new rule which detects the file traversal when extracting zip/tar archives
func NewArchive(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
calls := gosec.NewCallList()
calls.Add("path/filepath", "Join")
calls.Add("path", "Join")
return &archive{
calls: calls,
argType: "*archive/zip.File",
calls: calls,
argTypes: []string{"*archive/zip.File", "*archive/tar.Header"},
MetaData: gosec.MetaData{
ID: id,
Severity: gosec.Medium,
Confidence: gosec.High,
What: "File traversal when extracting zip archive",
What: "File traversal when extracting zip/tar archive",
},
}, []ast.Node{(*ast.CallExpr)(nil)}
}

View File

@@ -95,6 +95,7 @@ func NewDecompressionBombCheck(id string, conf gosec.Config) (gosec.Rule, []ast.
copyCalls := gosec.NewCallList()
copyCalls.Add("io", "Copy")
copyCalls.Add("io", "CopyBuffer")
return &decompressionBombCheck{
MetaData: gosec.MetaData{

View File

@@ -25,6 +25,7 @@ type readfile struct {
gosec.MetaData
gosec.CallList
pathJoin gosec.CallList
clean gosec.CallList
}
// ID returns the identifier for this rule
@@ -56,6 +57,21 @@ func (r *readfile) isJoinFunc(n ast.Node, c *gosec.Context) bool {
return false
}
// isFilepathClean checks if there is a filepath.Clean before assigning to a variable
func (r *readfile) isFilepathClean(n *ast.Ident, c *gosec.Context) bool {
if n.Obj.Kind != ast.Var {
return false
}
if node, ok := n.Obj.Decl.(*ast.AssignStmt); ok {
if call, ok := node.Rhs[0].(*ast.CallExpr); ok {
if clean := r.clean.ContainsPkgCallExpr(call, c, false); clean != nil {
return true
}
}
}
return false
}
// Match inspects AST nodes to determine if the match the methods `os.Open` or `ioutil.ReadFile`
func (r *readfile) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
if node := r.ContainsPkgCallExpr(n, c, false); node != nil {
@@ -77,7 +93,9 @@ func (r *readfile) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
if ident, ok := arg.(*ast.Ident); ok {
obj := c.Info.ObjectOf(ident)
if _, ok := obj.(*types.Var); ok && !gosec.TryResolve(ident, c) {
if _, ok := obj.(*types.Var); ok &&
!gosec.TryResolve(ident, c) &&
!r.isFilepathClean(ident, c) {
return gosec.NewIssue(c, n, r.ID(), r.What, r.Severity, r.Confidence), nil
}
}
@@ -90,6 +108,7 @@ func (r *readfile) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
func NewReadFile(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
rule := &readfile{
pathJoin: gosec.NewCallList(),
clean: gosec.NewCallList(),
CallList: gosec.NewCallList(),
MetaData: gosec.MetaData{
ID: id,
@@ -100,6 +119,8 @@ func NewReadFile(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
}
rule.pathJoin.Add("path/filepath", "Join")
rule.pathJoin.Add("path", "Join")
rule.clean.Add("path/filepath", "Clean")
rule.clean.Add("path/filepath", "Rel")
rule.Add("io/ioutil", "ReadFile")
rule.Add("os", "Open")
rule.Add("os", "OpenFile")

View File

@@ -39,6 +39,7 @@ var _ = Describe("gosec rules", func() {
}
err := pkg.Build()
Expect(err).ShouldNot(HaveOccurred())
Expect(pkg.PrintErrors()).Should(BeZero())
err = analyzer.Process(buildTags, pkg.Path)
Expect(err).ShouldNot(HaveOccurred())
issues, _, _ := analyzer.Report()

View File

@@ -134,7 +134,7 @@ func (t *insecureConfigTLS) mapVersion(version string) int16 {
func (t *insecureConfigTLS) checkVersion(n ast.Node, c *gosec.Context) *gosec.Issue {
if t.actualMaxVersion == 0 && t.actualMinVersion >= t.MinVersion {
// no warning is generated since the min version is grater than the secure min version
// no warning is generated since the min version is greater than the secure min version
return nil
}
if t.actualMinVersion < t.MinVersion {

View File

@@ -39,7 +39,9 @@ func NewIntermediateTLSCheck(id string, conf gosec.Config) (gosec.Rule, []ast.No
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305",
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
"TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
},
@@ -63,7 +65,9 @@ func NewOldTLSCheck(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305",
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
"TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",

View File

@@ -142,3 +142,8 @@ func (p *TestPackage) Pkgs() []*packages.Package {
}
return []*packages.Package{}
}
// PrintErrors prints to os.Stderr the accumulated errors of built packages
func (p *TestPackage) PrintErrors() int {
return packages.PrintErrors(p.Pkgs())
}

View File

@@ -582,7 +582,6 @@ import (
"fmt"
"log"
"net/http"
"net/http/pprof"
)
func main() {
@@ -699,12 +698,40 @@ func main() {
if err != nil {
panic(err)
}
io.Copy(os.Stdout, r)
_, err = io.Copy(os.Stdout, r)
if err != nil {
panic(err)
}
r.Close()
}`}, 1, gosec.NewConfig()}, {[]string{`
package main
import (
"bytes"
"compress/zlib"
"io"
"os"
)
func main() {
buff := []byte{120, 156, 202, 72, 205, 201, 201, 215, 81, 40, 207,
47, 202, 73, 225, 2, 4, 0, 0, 255, 255, 33, 231, 4, 147}
b := bytes.NewReader(buff)
r, err := zlib.NewReader(b)
if err != nil {
panic(err)
}
buf := make([]byte, 8)
_, err = io.CopyBuffer(os.Stdout, r, buf)
if err != nil {
panic(err)
}
r.Close()
}`}, 1, gosec.NewConfig()}, {[]string{`
package main
import (
"archive/zip"
"io"
@@ -1189,6 +1216,7 @@ func main() {
// command line arguments as it's arguments is considered dangerous
package main
import (
"context"
"log"
"os"
"os/exec"
@@ -1283,7 +1311,7 @@ import (
)
func RunCmd(command string) {
_, err := syscall.StartProcess(command, []string{}, nil)
_, _, err := syscall.StartProcess(command, []string{}, nil)
if err != nil {
fmt.Printf("Error: %v\n", err)
}
@@ -1558,9 +1586,64 @@ func main() {
log.Printf("Error: %v\n", err)
}
log.Print(body)
}`}, 1, gosec.NewConfig()}}
}`}, 1, gosec.NewConfig()}, {[]string{`
package main
// SampleCodeG305 - File path traversal when extracting zip archives
import (
"os"
"path/filepath"
)
func main() {
repoFile := "path_of_file"
cleanRepoFile := filepath.Clean(repoFile)
_, err := os.OpenFile(cleanRepoFile, os.O_RDONLY, 0600)
if err != nil {
panic(err)
}
}
`}, 0, gosec.NewConfig()}, {[]string{`
package main
import (
"os"
"path/filepath"
)
func openFile(filePath string) {
_, err := os.OpenFile(filepath.Clean(filePath), os.O_RDONLY, 0600)
if err != nil {
panic(err)
}
}
func main() {
repoFile := "path_of_file"
openFile(repoFile)
}
`}, 0, gosec.NewConfig()}, {[]string{`
package main
import (
"os"
"path/filepath"
)
func main() {
repoFile := "path_of_file"
relFile, err := filepath.Rel("./", repoFile)
if err != nil {
panic(err)
}
_, err = os.OpenFile(relFile, os.O_RDONLY, 0600)
if err != nil {
panic(err)
}
}
`}, 0, gosec.NewConfig()}}
// SampleCodeG305 - File path traversal when extracting zip/tar archives
SampleCodeG305 = []CodeSample{{[]string{`
package unzip
@@ -1652,6 +1735,76 @@ func unzip(archive, target string) error {
}
return nil
}`}, 1, gosec.NewConfig()}, {[]string{`
package zip
import (
"archive/zip"
"io"
"os"
"path"
)
func extractFile(f *zip.File, destPath string) error {
filePath := path.Join(destPath, f.Name)
os.MkdirAll(path.Dir(filePath), os.ModePerm)
rc, err := f.Open()
if err != nil {
return err
}
defer rc.Close()
fw, err := os.Create(filePath)
if err != nil {
return err
}
defer fw.Close()
if _, err = io.Copy(fw, rc); err != nil {
return err
}
if f.FileInfo().Mode()&os.ModeSymlink != 0 {
return nil
}
if err = os.Chtimes(filePath, f.ModTime(), f.ModTime()); err != nil {
return err
}
return os.Chmod(filePath, f.FileInfo().Mode())
}`}, 1, gosec.NewConfig()}, {[]string{`
package tz
import (
"archive/tar"
"io"
"os"
"path"
)
func extractFile(f *tar.Header, tr *tar.Reader, destPath string) error {
filePath := path.Join(destPath, f.Name)
os.MkdirAll(path.Dir(filePath), os.ModePerm)
fw, err := os.Create(filePath)
if err != nil {
return err
}
defer fw.Close()
if _, err = io.Copy(fw, tr); err != nil {
return err
}
if f.FileInfo().Mode()&os.ModeSymlink != 0 {
return nil
}
if err = os.Chtimes(filePath, f.FileInfo().ModTime(), f.FileInfo().ModTime()); err != nil {
return err
}
return os.Chmod(filePath, f.FileInfo().Mode())
}`}, 1, gosec.NewConfig()}}
// SampleCodeG306 - Poor permissions for WriteFile
@@ -1904,7 +2057,6 @@ func main() {
if err != nil {
fmt.Println(err)
}
}
}`}, 0, gosec.NewConfig()}}
// SampleCodeG403 - weak key strength
@@ -1959,7 +2111,7 @@ import (
"math/rand"
)
func main() {
gen := rand.New(rand.NewSource(10.4))
gen := rand.New(rand.NewSource(10))
bad := gen.Int()
println(bad)
}`}, 1, gosec.NewConfig()},
@@ -2079,10 +2231,11 @@ func printVector() {
fmt.Println()
}
func foo() (int, *string, string) {
func foo() (int, **string, *string) {
for _, item := range vector {
return 0, &item, item
}
return 0, nil, nil
}
func main() {
@@ -2093,7 +2246,7 @@ func main() {
printVector()
zero, c_star, c := foo()
fmt.Printf("%d %v %s", zero, c_start, c)
fmt.Printf("%d %v %s", zero, c_star, c)
}`,
}, 1, gosec.NewConfig()},
{[]string{`