mirror of
https://github.com/safedep/vet.git
synced 2025-12-12 22:23:59 -06:00
Merge pull request #19 from safedep/develop
Sync Develop with Main for Multiple Fixes
This commit is contained in:
commit
5939b9df10
@ -4,7 +4,10 @@
|
|||||||
helps engineering and security teams to identify potential issues in their open
|
helps engineering and security teams to identify potential issues in their open
|
||||||
source dependencies and evaluate them against organizational policies.
|
source dependencies and evaluate them against organizational policies.
|
||||||
|
|
||||||
|
[](https://api.securityscorecards.dev/projects/github.com/safedep/vet)
|
||||||
[](https://github.com/safedep/vet/actions/workflows/codeql.yml)
|
[](https://github.com/safedep/vet/actions/workflows/codeql.yml)
|
||||||
|
[](https://github.com/safedep/vet/actions/workflows/scorecard.yml)
|
||||||
|
|
||||||
|
|
||||||
## TL;DR
|
## TL;DR
|
||||||
|
|
||||||
|
|||||||
5
auth.go
5
auth.go
@ -1,6 +1,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"syscall"
|
"syscall"
|
||||||
@ -22,9 +23,7 @@ func newAuthCommand() *cobra.Command {
|
|||||||
Use: "auth",
|
Use: "auth",
|
||||||
Short: "Configure and verify Insights API authentication",
|
Short: "Configure and verify Insights API authentication",
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
fmt.Printf("You must choose an appropriate command: configure, verify\n")
|
return errors.New("a valid sub-command is required")
|
||||||
os.Exit(1)
|
|
||||||
return nil
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
2
go.mod
2
go.mod
@ -8,7 +8,7 @@ require (
|
|||||||
github.com/google/cel-go v0.13.0
|
github.com/google/cel-go v0.13.0
|
||||||
github.com/google/osv-scanner v1.1.0
|
github.com/google/osv-scanner v1.1.0
|
||||||
github.com/jedib0t/go-pretty/v6 v6.4.4
|
github.com/jedib0t/go-pretty/v6 v6.4.4
|
||||||
github.com/safedep/dry v0.0.0-20230203134955-367834d99b1c
|
github.com/safedep/dry v0.0.0-20230216112435-385c68e56634
|
||||||
github.com/sirupsen/logrus v1.9.0
|
github.com/sirupsen/logrus v1.9.0
|
||||||
github.com/spf13/cobra v1.6.1
|
github.com/spf13/cobra v1.6.1
|
||||||
github.com/stretchr/testify v1.8.1
|
github.com/stretchr/testify v1.8.1
|
||||||
|
|||||||
2
go.sum
2
go.sum
@ -45,6 +45,8 @@ github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ
|
|||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/safedep/dry v0.0.0-20230203134955-367834d99b1c h1:zbhTBT463mwcIuCq89GT8pFTU8UtGalBWFaa/wsgVXA=
|
github.com/safedep/dry v0.0.0-20230203134955-367834d99b1c h1:zbhTBT463mwcIuCq89GT8pFTU8UtGalBWFaa/wsgVXA=
|
||||||
github.com/safedep/dry v0.0.0-20230203134955-367834d99b1c/go.mod h1:yZ8R6kv4pR0yertVoxgBmnN4bvHT8TLubE7aahpWDDk=
|
github.com/safedep/dry v0.0.0-20230203134955-367834d99b1c/go.mod h1:yZ8R6kv4pR0yertVoxgBmnN4bvHT8TLubE7aahpWDDk=
|
||||||
|
github.com/safedep/dry v0.0.0-20230216112435-385c68e56634 h1:JRIzwT2Xo7TFH2O1gMJpHS5Fn6jDJdF+/+2JdyhzI3A=
|
||||||
|
github.com/safedep/dry v0.0.0-20230216112435-385c68e56634/go.mod h1:yZ8R6kv4pR0yertVoxgBmnN4bvHT8TLubE7aahpWDDk=
|
||||||
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
|
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
|
||||||
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||||
github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=
|
github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=
|
||||||
|
|||||||
66
internal/ui/progress.go
Normal file
66
internal/ui/progress.go
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
package ui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/jedib0t/go-pretty/v6/progress"
|
||||||
|
)
|
||||||
|
|
||||||
|
var progressWriter progress.Writer
|
||||||
|
|
||||||
|
func StartProgressWriter() {
|
||||||
|
pw := progress.NewWriter()
|
||||||
|
|
||||||
|
pw.SetTrackerLength(25)
|
||||||
|
pw.SetMessageWidth(20)
|
||||||
|
pw.SetSortBy(progress.SortByPercentDsc)
|
||||||
|
pw.SetStyle(progress.StyleDefault)
|
||||||
|
pw.SetOutputWriter(os.Stderr)
|
||||||
|
pw.SetTrackerPosition(progress.PositionRight)
|
||||||
|
pw.SetUpdateFrequency(time.Millisecond * 100)
|
||||||
|
pw.Style().Colors = progress.StyleColorsExample
|
||||||
|
pw.Style().Options.PercentFormat = "%4.1f%%"
|
||||||
|
pw.Style().Visibility.Pinned = true
|
||||||
|
pw.Style().Visibility.ETA = true
|
||||||
|
pw.Style().Visibility.Value = true
|
||||||
|
|
||||||
|
progressWriter = pw
|
||||||
|
go progressWriter.Render()
|
||||||
|
}
|
||||||
|
|
||||||
|
func StopProgressWriter() {
|
||||||
|
if progressWriter != nil {
|
||||||
|
progressWriter.Stop()
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TrackProgress(message string, total int) any {
|
||||||
|
tracker := progress.Tracker{Message: message, Total: int64(total),
|
||||||
|
Units: progress.UnitsDefault}
|
||||||
|
|
||||||
|
if progressWriter != nil {
|
||||||
|
progressWriter.AppendTracker(&tracker)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &tracker
|
||||||
|
}
|
||||||
|
|
||||||
|
func MarkTrackerAsDone(i any) {
|
||||||
|
if tracker, ok := i.(*progress.Tracker); ok {
|
||||||
|
tracker.MarkAsDone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func IncrementTrackerTotal(i any, count int) {
|
||||||
|
if tracker, ok := i.(*progress.Tracker); ok {
|
||||||
|
tracker.UpdateTotal(tracker.Total + int64(count))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func IncrementProgress(i any, count int) {
|
||||||
|
if tracker, ok := i.(*progress.Tracker); ok {
|
||||||
|
tracker.Increment(int64(count))
|
||||||
|
}
|
||||||
|
}
|
||||||
39
internal/ui/spinner.go
Normal file
39
internal/ui/spinner.go
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
package ui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var spinnerChan chan bool
|
||||||
|
|
||||||
|
func StartSpinner(msg string) {
|
||||||
|
style := `⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏`
|
||||||
|
frames := []rune(style)
|
||||||
|
length := len(frames)
|
||||||
|
|
||||||
|
spinnerChan = make(chan bool)
|
||||||
|
|
||||||
|
ticker := time.NewTicker(100 * time.Millisecond)
|
||||||
|
go func() {
|
||||||
|
pos := 0
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-spinnerChan:
|
||||||
|
ticker.Stop()
|
||||||
|
return
|
||||||
|
case <-ticker.C:
|
||||||
|
fmt.Printf("\r%s ... %s", msg, string(frames[pos%length]))
|
||||||
|
pos += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func StopSpinner() {
|
||||||
|
spinnerChan <- true
|
||||||
|
|
||||||
|
fmt.Printf("\r")
|
||||||
|
fmt.Println()
|
||||||
|
}
|
||||||
@ -2,96 +2,9 @@ package ui
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"os"
|
||||||
|
|
||||||
"github.com/jedib0t/go-pretty/v6/progress"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var progressWriter progress.Writer
|
func PrintBanner(s string) {
|
||||||
var spinnerChan chan bool
|
fmt.Fprintf(os.Stderr, s)
|
||||||
|
|
||||||
func StartSpinner(msg string) {
|
|
||||||
style := `⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏`
|
|
||||||
frames := []rune(style)
|
|
||||||
length := len(frames)
|
|
||||||
|
|
||||||
spinnerChan = make(chan bool)
|
|
||||||
|
|
||||||
ticker := time.NewTicker(100 * time.Millisecond)
|
|
||||||
go func() {
|
|
||||||
pos := 0
|
|
||||||
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-spinnerChan:
|
|
||||||
ticker.Stop()
|
|
||||||
return
|
|
||||||
case <-ticker.C:
|
|
||||||
fmt.Printf("\r%s ... %s", msg, string(frames[pos%length]))
|
|
||||||
pos += 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
func StopSpinner() {
|
|
||||||
spinnerChan <- true
|
|
||||||
|
|
||||||
fmt.Printf("\r")
|
|
||||||
fmt.Println()
|
|
||||||
}
|
|
||||||
|
|
||||||
func StartProgressWriter() {
|
|
||||||
pw := progress.NewWriter()
|
|
||||||
|
|
||||||
pw.SetTrackerLength(25)
|
|
||||||
pw.SetMessageWidth(20)
|
|
||||||
pw.SetSortBy(progress.SortByPercentDsc)
|
|
||||||
pw.SetStyle(progress.StyleDefault)
|
|
||||||
pw.SetTrackerPosition(progress.PositionRight)
|
|
||||||
pw.SetUpdateFrequency(time.Millisecond * 100)
|
|
||||||
pw.Style().Colors = progress.StyleColorsExample
|
|
||||||
pw.Style().Options.PercentFormat = "%4.1f%%"
|
|
||||||
pw.Style().Visibility.Pinned = true
|
|
||||||
pw.Style().Visibility.ETA = true
|
|
||||||
pw.Style().Visibility.Value = true
|
|
||||||
|
|
||||||
progressWriter = pw
|
|
||||||
go progressWriter.Render()
|
|
||||||
}
|
|
||||||
|
|
||||||
func StopProgressWriter() {
|
|
||||||
if progressWriter != nil {
|
|
||||||
progressWriter.Stop()
|
|
||||||
time.Sleep(1 * time.Second)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TrackProgress(message string, total int) any {
|
|
||||||
tracker := progress.Tracker{Message: message, Total: int64(total),
|
|
||||||
Units: progress.UnitsDefault}
|
|
||||||
|
|
||||||
if progressWriter != nil {
|
|
||||||
progressWriter.AppendTracker(&tracker)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &tracker
|
|
||||||
}
|
|
||||||
|
|
||||||
func MarkTrackerAsDone(i any) {
|
|
||||||
if tracker, ok := i.(*progress.Tracker); ok {
|
|
||||||
tracker.MarkAsDone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func IncrementTrackerTotal(i any, count int) {
|
|
||||||
if tracker, ok := i.(*progress.Tracker); ok {
|
|
||||||
tracker.UpdateTotal(tracker.Total + int64(count))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func IncrementProgress(i any, count int) {
|
|
||||||
if tracker, ok := i.(*progress.Tracker); ok {
|
|
||||||
tracker.Increment(int64(count))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
3
main.go
3
main.go
@ -7,6 +7,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/safedep/dry/utils"
|
"github.com/safedep/dry/utils"
|
||||||
|
"github.com/safedep/vet/internal/ui"
|
||||||
"github.com/safedep/vet/pkg/common/logger"
|
"github.com/safedep/vet/pkg/common/logger"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
@ -68,7 +69,7 @@ func main() {
|
|||||||
func printBanner() {
|
func printBanner() {
|
||||||
bRet, err := strconv.ParseBool(os.Getenv("VET_DISABLE_BANNER"))
|
bRet, err := strconv.ParseBool(os.Getenv("VET_DISABLE_BANNER"))
|
||||||
if (err != nil) || (!bRet) {
|
if (err != nil) || (!bRet) {
|
||||||
fmt.Print(banner)
|
ui.PrintBanner(banner)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -85,6 +85,8 @@ func (pw *parserWrapper) Ecosystem() string {
|
|||||||
return models.EcosystemPub
|
return models.EcosystemPub
|
||||||
case "requirements.txt":
|
case "requirements.txt":
|
||||||
return models.EcosystemPyPI
|
return models.EcosystemPyPI
|
||||||
|
case "Pipfile.lock":
|
||||||
|
return models.EcosystemPyPI
|
||||||
case "yarn.lock":
|
case "yarn.lock":
|
||||||
return models.EcosystemNpm
|
return models.EcosystemNpm
|
||||||
case "gradle.lockfile":
|
case "gradle.lockfile":
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import (
|
|||||||
|
|
||||||
func TestListParser(t *testing.T) {
|
func TestListParser(t *testing.T) {
|
||||||
parsers := List()
|
parsers := List()
|
||||||
assert.Equal(t, 9, len(parsers))
|
assert.Equal(t, 10, len(parsers))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInvalidEcosystemMapping(t *testing.T) {
|
func TestInvalidEcosystemMapping(t *testing.T) {
|
||||||
|
|||||||
@ -26,12 +26,17 @@ const (
|
|||||||
summaryWeightUnpopular = 2
|
summaryWeightUnpopular = 2
|
||||||
summaryWeightMajorDrift = 2
|
summaryWeightMajorDrift = 2
|
||||||
|
|
||||||
|
tagVuln = "vulnerabiity"
|
||||||
|
tagUnpopular = "low popularity"
|
||||||
|
tagDrift = "drift"
|
||||||
|
|
||||||
summaryReportMaxUpgradeAdvice = 5
|
summaryReportMaxUpgradeAdvice = 5
|
||||||
)
|
)
|
||||||
|
|
||||||
type summaryReporterRemediationData struct {
|
type summaryReporterRemediationData struct {
|
||||||
pkg *models.Package
|
pkg *models.Package
|
||||||
score int
|
score int
|
||||||
|
tags []string
|
||||||
}
|
}
|
||||||
|
|
||||||
type summaryReporter struct {
|
type summaryReporter struct {
|
||||||
@ -100,7 +105,7 @@ func (r *summaryReporter) processForVersionDrift(pkg *models.Package) {
|
|||||||
driftType, _ := semver.Diff(version, latestVersion)
|
driftType, _ := semver.Diff(version, latestVersion)
|
||||||
if driftType.IsMajor() {
|
if driftType.IsMajor() {
|
||||||
r.summary.metrics.drifts += 1
|
r.summary.metrics.drifts += 1
|
||||||
r.addPkgForRemediationAdvice(pkg, summaryWeightMajorDrift)
|
r.addPkgForRemediationAdvice(pkg, summaryWeightMajorDrift, tagDrift)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,7 +126,7 @@ func (r *summaryReporter) processForPopularity(pkg *models.Package) {
|
|||||||
|
|
||||||
if (strings.EqualFold(projectType, "github")) && (starsCount < 10) {
|
if (strings.EqualFold(projectType, "github")) && (starsCount < 10) {
|
||||||
r.summary.metrics.unpopular += 1
|
r.summary.metrics.unpopular += 1
|
||||||
r.addPkgForRemediationAdvice(pkg, summaryWeightUnpopular)
|
r.addPkgForRemediationAdvice(pkg, summaryWeightUnpopular, tagUnpopular)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -141,33 +146,39 @@ func (r *summaryReporter) processForVulns(pkg *models.Package) {
|
|||||||
switch risk {
|
switch risk {
|
||||||
case insightapi.PackageVulnerabilitySeveritiesRiskCRITICAL:
|
case insightapi.PackageVulnerabilitySeveritiesRiskCRITICAL:
|
||||||
r.summary.vulns.critical += 1
|
r.summary.vulns.critical += 1
|
||||||
r.addPkgForRemediationAdvice(pkg, summaryWeightCriticalVuln)
|
r.addPkgForRemediationAdvice(pkg, summaryWeightCriticalVuln, tagVuln)
|
||||||
break
|
break
|
||||||
case insightapi.PackageVulnerabilitySeveritiesRiskHIGH:
|
case insightapi.PackageVulnerabilitySeveritiesRiskHIGH:
|
||||||
r.summary.vulns.high += 1
|
r.summary.vulns.high += 1
|
||||||
r.addPkgForRemediationAdvice(pkg, summaryWeightHighVuln)
|
r.addPkgForRemediationAdvice(pkg, summaryWeightHighVuln, tagVuln)
|
||||||
break
|
break
|
||||||
case insightapi.PackageVulnerabilitySeveritiesRiskMEDIUM:
|
case insightapi.PackageVulnerabilitySeveritiesRiskMEDIUM:
|
||||||
r.summary.vulns.medium += 1
|
r.summary.vulns.medium += 1
|
||||||
r.addPkgForRemediationAdvice(pkg, summaryWeightMediumVuln)
|
r.addPkgForRemediationAdvice(pkg, summaryWeightMediumVuln, tagVuln)
|
||||||
break
|
break
|
||||||
case insightapi.PackageVulnerabilitySeveritiesRiskLOW:
|
case insightapi.PackageVulnerabilitySeveritiesRiskLOW:
|
||||||
r.summary.vulns.low += 1
|
r.summary.vulns.low += 1
|
||||||
r.addPkgForRemediationAdvice(pkg, summaryWeightLowVuln)
|
r.addPkgForRemediationAdvice(pkg, summaryWeightLowVuln, tagVuln)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *summaryReporter) addPkgForRemediationAdvice(pkg *models.Package, weight int) {
|
func (r *summaryReporter) addPkgForRemediationAdvice(pkg *models.Package,
|
||||||
|
weight int, tag string) {
|
||||||
if _, ok := r.remediationScores[pkg.Id()]; !ok {
|
if _, ok := r.remediationScores[pkg.Id()]; !ok {
|
||||||
r.remediationScores[pkg.Id()] = &summaryReporterRemediationData{
|
r.remediationScores[pkg.Id()] = &summaryReporterRemediationData{
|
||||||
pkg: pkg,
|
pkg: pkg,
|
||||||
|
tags: []string{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
r.remediationScores[pkg.Id()].score += weight
|
r.remediationScores[pkg.Id()].score += weight
|
||||||
|
|
||||||
|
if utils.FindInSlice(r.remediationScores[pkg.Id()].tags, tag) == -1 {
|
||||||
|
r.remediationScores[pkg.Id()].tags = append(r.remediationScores[pkg.Id()].tags, tag)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *summaryReporter) Finish() error {
|
func (r *summaryReporter) Finish() error {
|
||||||
@ -181,11 +192,10 @@ func (r *summaryReporter) Finish() error {
|
|||||||
fmt.Println()
|
fmt.Println()
|
||||||
fmt.Println(text.Faint.Sprint(summaryListPrependText, r.manifestCountStatement()))
|
fmt.Println(text.Faint.Sprint(summaryListPrependText, r.manifestCountStatement()))
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
|
|
||||||
r.renderRemediationAdvice()
|
r.renderRemediationAdvice()
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
fmt.Println("Install as a security gate in CI for incremental scan and blocking risky dependencies")
|
|
||||||
fmt.Println("Run `vet ci` to generate CI scripts")
|
|
||||||
fmt.Println()
|
|
||||||
fmt.Println("Run with `vet --filter=\"...\"` for custom filters to identify risky libraries")
|
fmt.Println("Run with `vet --filter=\"...\"` for custom filters to identify risky libraries")
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
fmt.Println("For more details", text.Bold.Sprint("https://github.com/safedep/vet"))
|
fmt.Println("For more details", text.Bold.Sprint("https://github.com/safedep/vet"))
|
||||||
@ -221,7 +231,7 @@ func (r *summaryReporter) renderRemediationAdvice() {
|
|||||||
tbl.SetOutputMirror(os.Stdout)
|
tbl.SetOutputMirror(os.Stdout)
|
||||||
tbl.SetStyle(table.StyleLight)
|
tbl.SetStyle(table.StyleLight)
|
||||||
|
|
||||||
tbl.AppendHeader(table.Row{"Package", "Update To", "Risk Score"})
|
tbl.AppendHeader(table.Row{"Package", "Update To", "Impact"})
|
||||||
for idx, sp := range sortedPackages {
|
for idx, sp := range sortedPackages {
|
||||||
if idx >= summaryReportMaxUpgradeAdvice {
|
if idx >= summaryReportMaxUpgradeAdvice {
|
||||||
break
|
break
|
||||||
@ -234,6 +244,17 @@ func (r *summaryReporter) renderRemediationAdvice() {
|
|||||||
utils.SafelyGetValue(insight.PackageCurrentVersion),
|
utils.SafelyGetValue(insight.PackageCurrentVersion),
|
||||||
sp.score,
|
sp.score,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
tagText := ""
|
||||||
|
for _, t := range sp.tags {
|
||||||
|
tagText += text.BgMagenta.Sprint(" "+t+" ") + " "
|
||||||
|
}
|
||||||
|
|
||||||
|
tbl.AppendRow(table.Row{
|
||||||
|
tagText, "", "",
|
||||||
|
})
|
||||||
|
|
||||||
|
tbl.AppendSeparator()
|
||||||
}
|
}
|
||||||
|
|
||||||
tbl.Render()
|
tbl.Render()
|
||||||
@ -255,7 +276,7 @@ func (r *summaryReporter) packageNameForRemediationAdvice(pkg *models.Package) s
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *summaryReporter) vulnSummaryStatement() string {
|
func (r *summaryReporter) vulnSummaryStatement() string {
|
||||||
return fmt.Sprintf("%d critical, %d high and %d other vulnerabilities were identifier",
|
return fmt.Sprintf("%d critical, %d high and %d other vulnerabilities were identified",
|
||||||
r.summary.vulns.critical, r.summary.vulns.high,
|
r.summary.vulns.critical, r.summary.vulns.high,
|
||||||
r.summary.vulns.medium+r.summary.vulns.low)
|
r.summary.vulns.medium+r.summary.vulns.low)
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user