From a945387dd384ec865937b695ac4d879d904efbd6 Mon Sep 17 00:00:00 2001 From: DJ Schleen Date: Mon, 6 Nov 2023 20:45:26 -0700 Subject: [PATCH] Fixes an issue where return code was 10 if no severity flag was set --- .vscode/launch.json | 12 ++++++++++-- README.md | 30 +++++++++++++++++++++++++++++ cmd/scan.go | 17 +++++++++-------- go.mod | 12 ++++++------ go.sum | 26 ++++++++++++------------- lib/util.go | 31 +++++++----------------------- lib/util_test.go | 46 +-------------------------------------------- 7 files changed, 76 insertions(+), 98 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index ab42517..7b15e2b 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -33,12 +33,20 @@ "args": ["--provider=ossindex", "--debug=true", "scan", "./_TESTDATA_/sbom"] }, { - "name": "Debug File (OSS Index - juiceshop, fail = moderate)", + "name": "Debug File (OSS Index - juiceshop, severity = moderate)", "type": "go", "request": "launch", "mode": "auto", "program": "${workspaceFolder}/main.go", - "args": ["--debug=true", "--fail=critical", "--provider=ossindex", "scan", "./_TESTDATA_/sbom/juiceshop.cyclonedx.json"] + "args": ["--debug=true", "--severity=moderate", "--provider=ossindex", "scan", "./_TESTDATA_/sbom/juiceshop.cyclonedx.json"] + }, + { + "name": "Debug File (OSS Index - juiceshop, severity = critical)", + "type": "go", + "request": "launch", + "mode": "auto", + "program": "${workspaceFolder}/main.go", + "args": ["--debug=true", "--severity=moderate", "--provider=ossindex", "scan", "./_TESTDATA_/sbom/juiceshop.cyclonedx.json"] }, { "name": "Debug File (OSV- cargo-valid)", diff --git a/README.md b/README.md index 692bbb5..03f00b8 100644 --- a/README.md +++ b/README.md @@ -165,6 +165,36 @@ To use the ```bomber.ignore``` file, use the syntax as follows: bomber --ignore-file=bomber.ignore scan bom.json ``` +## Filtering Output + +You may set the severity level with the ```--severity``` flag in order to return specific vulnerability severities. For example, if you set ```--severity=moderate``` only vulnerabilities with a severity of ```MODERATE``` or above will be returned. + +For example, the following command will return only high and critical vulnerabilities. + +``` bash +bomber --severity=high scan bom.json +``` +## Return codes + + + +| Option | Return Code | +|---|---| +| NONE (default) | 0 | +| ERROR | 1 | +| UNSPECIFIED (This is a status where the provider gives us something wacky, or no info) | 10 | +| LOW | 11 | +| MODERATE | 12 | +| HIGH | 13 | +| CRITICAL | 14 | + +0 is an "I don't care about filters" value and is the default (shows all output) +1 is that an error occurred +... +13 means at least 1 HIGH *or* "1" critical is found +14 means at least 1 CRITICAL is found. + + ## Data Enrichment ```bomber``` has the ability to enrich vulnerability data it obtains from the [Providers](#providers). The first "enricher" we have implemented for is for [EPSS](https://www.first.org/epss/) diff --git a/cmd/scan.go b/cmd/scan.go index b91e46f..897c554 100644 --- a/cmd/scan.go +++ b/cmd/scan.go @@ -29,7 +29,7 @@ var ( renderer models.Renderer provider models.Provider ignoreFile string - failSeverity string + severity string // summary, detailed bool scanCmd = &cobra.Command{ @@ -101,11 +101,11 @@ var ( } //Get rid of the packages that have a vulnerability lower than its fail severity - if failSeverity != "" { + if severity != "" { for i, p := range response { vulns := []models.Vulnerability{} for _, v := range p.Vulnerabilities { - fs := int(lib.ParseFailSeverity(failSeverity)) + fs := lib.ParseSeverity(severity) vs := lib.ParseSeverity(v.Severity) if vs >= fs { vulns = append(vulns, v) @@ -142,11 +142,12 @@ var ( if err = renderer.Render(results); err != nil { log.Println(err) } - if failSeverity != "" { - log.Printf("fail severity: %x\n", int(lib.ParseFailSeverity(failSeverity))) - os.Exit(int(lib.ParseFailSeverity(failSeverity))) + failSeverity := lib.ParseSeverity(severity) + if severity != "" { + log.Printf("fail severity: %d", failSeverity) + os.Exit(failSeverity) } - + log.Printf("Fail severity: %d", failSeverity) } else { util.PrintInfo("No packages were detected. Nothing has been scanned.") } @@ -161,5 +162,5 @@ func init() { scanCmd.PersistentFlags().StringVar(&credentials.Token, "token", "", "the API token for the provider being used.") scanCmd.PersistentFlags().StringVar(&providerName, "provider", "osv", "the vulnerability provider (ossindex, osv).") scanCmd.PersistentFlags().StringVar(&ignoreFile, "ignore-file", "", "an optional file containing CVEs to ignore when rendering output.") - scanCmd.PersistentFlags().StringVar(&failSeverity, "fail", "undefined", "anything above this severity will be returned with non-zero error code.") + scanCmd.PersistentFlags().StringVar(&severity, "severity", "", "anything equal to or above this severity will be returned with non-zero error code.") } diff --git a/go.mod b/go.mod index 36513c3..64654f8 100644 --- a/go.mod +++ b/go.mod @@ -10,13 +10,13 @@ require ( github.com/devops-kung-fu/common v0.2.6 github.com/gookit/color v1.5.4 github.com/jarcoal/httpmock v1.3.0 - github.com/jedib0t/go-pretty/v6 v6.4.8 + github.com/jedib0t/go-pretty/v6 v6.4.9 github.com/kirinlabs/HttpRequest v1.1.1 github.com/microcosm-cc/bluemonday v1.0.26 github.com/package-url/packageurl-go v0.1.2 github.com/remeh/sizedwaitgroup v1.0.0 github.com/spf13/afero v1.10.0 - github.com/spf13/cobra v1.7.0 + github.com/spf13/cobra v1.8.0 github.com/stretchr/testify v1.8.4 k8s.io/utils v0.0.0-20230726121419-3b25d923346b ) @@ -31,9 +31,9 @@ require ( require ( github.com/aymerick/douceur v0.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/fatih/color v1.15.0 // indirect + github.com/fatih/color v1.16.0 // indirect github.com/gomarkdown/markdown v0.0.0-20230922112808-5421fefb8386 - github.com/gorilla/css v1.0.0 // indirect + github.com/gorilla/css v1.0.1 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect @@ -43,8 +43,8 @@ require ( github.com/spf13/pflag v1.0.5 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect golang.org/x/net v0.17.0 // indirect - golang.org/x/sys v0.13.0 // indirect - golang.org/x/text v0.13.0 // indirect + golang.org/x/sys v0.14.0 // indirect + golang.org/x/text v0.14.0 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index e66d339..346aeac 100644 --- a/go.sum +++ b/go.sum @@ -54,7 +54,7 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -67,8 +67,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= -github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -130,8 +130,8 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0= github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w= -github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= -github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= +github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8= +github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -140,8 +140,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jarcoal/httpmock v1.3.0 h1:2RJ8GP0IIaWwcC9Fp2BmVi8Kog3v2Hn7VXM3fTd+nuc= github.com/jarcoal/httpmock v1.3.0/go.mod h1:3yb8rc4BI7TCBhFY8ng0gjuLKJNquuDNiPaZjnENuYg= -github.com/jedib0t/go-pretty/v6 v6.4.8 h1:HiNzyMSEpsBaduKhmK+CwcpulEeBrTmxutz4oX/oWkg= -github.com/jedib0t/go-pretty/v6 v6.4.8/go.mod h1:Ndk3ase2CkQbXLLNf5QDHoYb6J9WtVfmHZu9n8rk2xs= +github.com/jedib0t/go-pretty/v6 v6.4.9 h1:vZ6bjGg2eBSrJn365qlxGcaWu09Id+LHtrfDWlB2Usc= +github.com/jedib0t/go-pretty/v6 v6.4.9/go.mod h1:Ndk3ase2CkQbXLLNf5QDHoYb6J9WtVfmHZu9n8rk2xs= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/kirinlabs/HttpRequest v1.1.1 h1:eBbFzpRd/Y7vQhRY30frHK3yAJiT1wDlB31Ryzyklc0= @@ -189,8 +189,8 @@ github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6po github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/spf13/afero v1.10.0 h1:EaGW2JJh15aKOejeuJ+wpFSHnbd7GE6Wvp3TsNhb6LY= github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= -github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= -github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= +github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= +github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -355,8 +355,8 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= @@ -368,8 +368,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= diff --git a/lib/util.go b/lib/util.go index 5eca455..258fa33 100644 --- a/lib/util.go +++ b/lib/util.go @@ -45,35 +45,18 @@ func AdjustSummary(severity string, summary *models.Summary) { // ParseSeverity takes a severity string and returns an int func ParseSeverity(severity string) int { severity = strings.ToUpper(severity) - switch severity { case "LOW": - return 11 + return int(models.LOW) case "MODERATE": - return 12 + return int(models.MODERATE) case "HIGH": - return 13 + return int(models.HIGH) case "CRITICAL": - return 14 - default: - return 10 - } -} - -// ParseFailSeverity takes a string and returns a FailSeverity enum -func ParseFailSeverity(s string) models.FailSeverity { - s = strings.ToLower(s) - - switch s { - case "low": - return models.LOW - case "moderate": - return models.MODERATE - case "high": - return models.HIGH - case "critical": - return models.CRITICAL + return int(models.CRITICAL) + case "UNDEFINED": + return int(models.UNDEFINED) default: - return models.UNDEFINED + return 0 } } diff --git a/lib/util_test.go b/lib/util_test.go index 68a2979..4abb49b 100644 --- a/lib/util_test.go +++ b/lib/util_test.go @@ -80,7 +80,7 @@ func TestParseSeverity(t *testing.T) { t.Run("Invalid severity: undefined", func(t *testing.T) { severity := "invalid" - expected := 10 + expected := 0 result := ParseSeverity(severity) assert.Equal(t, expected, result) }) @@ -92,47 +92,3 @@ func TestParseSeverity(t *testing.T) { assert.Equal(t, expected, result) }) } - -func TestParseFailSeverity(t *testing.T) { - t.Run("Valid severity: low", func(t *testing.T) { - s := "low" - expected := models.LOW - result := ParseFailSeverity(s) - assert.Equal(t, expected, result) - }) - - t.Run("Valid severity: moderate", func(t *testing.T) { - s := "moderate" - expected := models.MODERATE - result := ParseFailSeverity(s) - assert.Equal(t, expected, result) - }) - - t.Run("Valid severity: high", func(t *testing.T) { - s := "high" - expected := models.HIGH - result := ParseFailSeverity(s) - assert.Equal(t, expected, result) - }) - - t.Run("Valid severity: critical", func(t *testing.T) { - s := "critical" - expected := models.CRITICAL - result := ParseFailSeverity(s) - assert.Equal(t, expected, result) - }) - - t.Run("Invalid severity: undefined", func(t *testing.T) { - s := "invalid" - expected := models.UNDEFINED - result := ParseFailSeverity(s) - assert.Equal(t, expected, result) - }) - - t.Run("Mixed case severity: moderate", func(t *testing.T) { - s := "MoDerAte" - expected := models.MODERATE - result := ParseFailSeverity(s) - assert.Equal(t, expected, result) - }) -}