diff --git a/README.md b/README.md index e15925d..79acd5e 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,6 @@ [![Go Report Card](https://goreportcard.com/badge/github.com/devops-kung-fu/bomber)](https://goreportcard.com/report/github.com/devops-kung-fu/bomber) [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/6409/badge)](https://bestpractices.coreinfrastructure.org/projects/6409) [![codecov](https://codecov.io/gh/devops-kung-fu/bomber/branch/main/graph/badge.svg?token=P9WBOBQTOB)](https://codecov.io/gh/devops-kung-fu/bomber) -[![SBOM](https://img.shields.io/badge/CyloneDX-SBOM-informational)](sbom/bomber.cyclonedx.json) ```bomber``` is an application that scans SBOMs for security vulnerabilities. @@ -81,7 +80,7 @@ If you wish, you can move the ```bomber``` binary to your ```/usr/local/bin``` d To install ```bomber```, [download the latest release](https://github.com/devops-kung-fu/bomber/releases) for your platform and install locally. For example, install ```bomber``` on Ubuntu: ```bash -dpkg -i bomber_0.4.1_linux_arm64.deb +dpkg -i bomber_0.5.0_linux_arm64.deb ``` ## Using bomber @@ -97,7 +96,7 @@ Note that the default output for ```bomber``` is to STDOUT. Options to output in bomber scan cyclonedx.sbom.json # Using a provider that requires credentials (ossindex) -bomber scan --provider=xxx --username=xxx --token=xxx spdx-sbom.json +bomber scan --provider=xxx --username=xxx --token=xxx [sbom.json] ``` If the provider finds vulnerabilities you'll see an output similar to the following: @@ -174,24 +173,13 @@ For example, the following command will return only high and critical vulnerabil ``` bash bomber --severity=high scan bom.json ``` -## Highest Severity Return Codes (Experimental) - -Using the flag ```--exitcode```, will return with an exit code representing the highest vulnerability severity found. Without this flag you can expect an exit code of ```0``` for success, or ```1``` if an error was encountered. - -Assuming there is no error, the following values will be returned by ```bomber``` when ```--exitcode``` - -| Severity | Return Code | -|---|---| -| UNSPECIFIED (This is a status where the provider gives us something wacky, or no info) | 10 | -| LOW | 11 | -| MODERATE | 12 | -| HIGH | 13 | -| CRITICAL | 14 | ## 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/) +**NOTE:** EPSS scoring is no longer default in ```bomber 0.5.0 and above```. to show EPSS scores, ensure you use the ```--enrich=epss``` flag. + ### Exploit Prediction Scoring System (EPSS) [EPSS](https://www.first.org/epss/) stands for Exploit Prediction Scoring System and is framework that predicts the probability of a vulnerability being exploited. [EPSS](https://www.first.org/epss/) is often used to help in identifying high risk vulnerabilities to prioritize for remediation. @@ -221,7 +209,35 @@ export BOMBER_PROVIDER_USERNAME={{your OSS Index user name}} export BOMBER_PROVIDER_TOKEN={{your OSS Index API Token}} ``` -### Messing around +## Experimantal Features + +### Highest Severity Return Codes (Experimental) + +Using the flag ```--exitcode```, will return with an exit code representing the highest vulnerability severity found. Without this flag you can expect an exit code of ```0``` for success, or ```1``` if an error was encountered. + +Assuming there is no error, the following values will be returned by ```bomber``` when ```--exitcode``` + +| Severity | Return Code | +| -------------------------------------------------------------------------------------- | ----------- | +| UNSPECIFIED (This is a status where the provider gives us something wacky, or no info) | 10 | +| LOW | 11 | +| MODERATE | 12 | +| HIGH | 13 | +| CRITICAL | 14 | + +### OpenAI AI Enriched HTML Report Output + +```bomber``` now contains an experimental feature that enriches the description of vulnerabilities in a ```html``` output. This feature takes a vulnerability and changes the description into something more understandable for a non-technical user. + +**NOTE**: This feature is in a major alpha state at this time. It is extremely slow, and the output isn't formatted very well. + +To use this feature, you will need to provide an OpenAI API key. You can either pass this key into the CLI using the ```--openai-api-key={{your OpenAI API Key}}``` or add an environment variable: + +``` bash +export OPENAI_API_KEY={{your OpenAI API Key}} +``` + +## Messing around If you want to kick the tires on ```bomber``` you'll find a selection of test SBOMs in the [test](_TESTDATA_/sbom/) folder. @@ -237,7 +253,7 @@ If you would like to contribute to the development of ```bomber``` please refer ## Software Bill of Materials ```bomber``` uses Syft to generate a Software Bill of Materials every time a developer commits code to this repository (as long as [Hookz](https://github.com/devops-kung-fu/hookz) is being used and is has been initialized in the working directory). More information for CycloneDX is available [here](https://cyclonedx.org). - + The current CycloneDX SBOM for ```bomber``` is available [here](./sbom/bomber.cyclonedx.json). ## Sponsors diff --git a/cmd/root.go b/cmd/root.go index f0524c6..d775bc2 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -2,11 +2,13 @@ package cmd import ( + "context" "fmt" "io" "log" "os" + "github.com/google/go-github/github" "github.com/gookit/color" "github.com/spf13/afero" "github.com/spf13/cobra" @@ -38,11 +40,7 @@ var ( fmt.Println("https://github.com/devops-kung-fu/bomber") fmt.Printf("Version: %s\n", version) fmt.Println() - //TODO: Github appears to have added the need for a PAT to call this endpoint now. Revisit later. - // latestVersion, _ := github.LatestReleaseTag("devops-kung-fu", "bomber") - // if !strings.Contains(latestVersion, version) { - // color.Yellow.Printf("A newer version of bomber is available (%s)\n\n", latestVersion) - // } + checkForNewVersion(version) } }, } @@ -60,3 +58,19 @@ func init() { rootCmd.PersistentFlags().BoolVar(&debug, "debug", false, "displays debug level log messages.") rootCmd.PersistentFlags().StringVar(&output, "output", "stdout", "how bomber should output findings (json, html, ai, stdout)") } + +func checkForNewVersion(currentVersion string) { + ctx := context.Background() + client := github.NewClient(nil) + + release, _, err := client.Repositories.GetLatestRelease(ctx, "devops-kung-fu", "bomber") + if err != nil { + fmt.Printf("Error fetching latest release: %v\n", err) + return + } + + latestVersion := release.GetTagName()[1:] // Remove leading 'v' + if latestVersion != currentVersion { + color.Yellow.Printf("A newer version of bomber is available (%s)\n\n", latestVersion) + } +} diff --git a/go.mod b/go.mod index b388761..0970705 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,7 @@ require ( github.com/devops-kung-fu/common v0.2.6 github.com/go-resty/resty/v2 v2.14.0 github.com/gomarkdown/markdown v0.0.0-20240730141124-034f12af3bf6 + github.com/google/go-github v17.0.0+incompatible github.com/gookit/color v1.5.4 github.com/jarcoal/httpmock v1.3.1 github.com/jedib0t/go-pretty/v6 v6.5.9 @@ -21,6 +22,8 @@ require ( github.com/stretchr/testify v1.9.0 ) +require github.com/google/go-querystring v1.1.0 // indirect + require ( github.com/aymerick/douceur v0.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect @@ -32,12 +35,12 @@ require ( github.com/mattn/go-runewidth v0.0.16 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rivo/uniseg v0.4.7 // indirect - github.com/sashabaranov/go-openai v1.27.1 + github.com/sashabaranov/go-openai v1.28.1 github.com/spf13/pflag v1.0.5 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect - golang.org/x/net v0.27.0 // indirect - golang.org/x/sys v0.23.0 // indirect - golang.org/x/term v0.22.0 // indirect - golang.org/x/text v0.16.0 // indirect + golang.org/x/net v0.28.0 // indirect + golang.org/x/sys v0.24.0 // indirect + golang.org/x/term v0.23.0 // indirect + golang.org/x/text v0.17.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 02b6652..364849e 100644 --- a/go.sum +++ b/go.sum @@ -17,7 +17,13 @@ github.com/go-resty/resty/v2 v2.14.0 h1:/rhkzsAqGQkozwfKS5aFAbb6TyKd3zyFRWcdRXLP github.com/go-resty/resty/v2 v2.14.0/go.mod h1:IW6mekUOsElt9C7oWr0XRt9BNSD6D5rr9mhk6NjmNHg= github.com/gomarkdown/markdown v0.0.0-20240730141124-034f12af3bf6 h1:ZPy+2XJ8u0bB3sNFi+I72gMEMS7MTg7aZCCXPOjV8iw= github.com/gomarkdown/markdown v0.0.0-20240730141124-034f12af3bf6/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY= +github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= 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.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8= @@ -49,8 +55,8 @@ github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sashabaranov/go-openai v1.27.1 h1:7Nx6db5NXbcoutNmAUQulEQZEpHG/SkzfexP2X5RWMk= -github.com/sashabaranov/go-openai v1.27.1/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg= +github.com/sashabaranov/go-openai v1.28.1 h1:aREx6faUTeOZNMDTNGAY8B9vNmmN7qoGvDV0Ke2J1Mc= +github.com/sashabaranov/go-openai v1.28.1/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= @@ -91,8 +97,9 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= -golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= +golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -112,8 +119,8 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM= -golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= +golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -122,8 +129,9 @@ golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= -golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= +golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= +golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= @@ -132,8 +140,9 @@ golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= +golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -143,6 +152,7 @@ golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=