diff --git a/pkg/report/table/table_test.go b/pkg/report/table/table_test.go index b66828241634..d52dda0dc232 100644 --- a/pkg/report/table/table_test.go +++ b/pkg/report/table/table_test.go @@ -73,6 +73,7 @@ Total: 1 (MEDIUM: 0, HIGH: 1) }, } + t.Setenv("TRIVY_DISABLE_VEX_NOTICE", "1") for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { tableWritten := bytes.Buffer{} diff --git a/pkg/report/table/vulnerability.go b/pkg/report/table/vulnerability.go index 03435fd92b96..450349ed5fcb 100644 --- a/pkg/report/table/vulnerability.go +++ b/pkg/report/table/vulnerability.go @@ -3,12 +3,14 @@ package table import ( "bytes" "fmt" + "os" "path/filepath" "slices" "sort" "strings" "sync" + "github.com/fatih/color" "github.com/samber/lo" "github.com/xlab/treeprint" @@ -18,11 +20,29 @@ import ( ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" "github.com/aquasecurity/trivy/pkg/log" "github.com/aquasecurity/trivy/pkg/types" + "github.com/aquasecurity/trivy/pkg/version/doc" ) -var showSuppressedOnce = sync.OnceFunc(func() { - log.Info(`Some vulnerabilities have been ignored/suppressed. Use the "--show-suppressed" flag to display them.`) -}) +const ( + vexNotice = ` +For OSS Maintainers: VEX Notice +-------------------------------- +If you're an OSS maintainer and Trivy has detected vulnerabilities in your project that you believe are not actually exploitable, consider issuing a VEX (Vulnerability Exploitability eXchange) statement. +VEX allows you to communicate the actual status of vulnerabilities in your project, improving security transparency and reducing false positives for your users. +Learn more and start using VEX: %s + +To disable this notice, set the TRIVY_DISABLE_VEX_NOTICE environment variable. + +` + envDisableNotice = "TRIVY_DISABLE_VEX_NOTICE" +) + +var ( + showVEXNoticeOnce = &sync.Once{} + showSuppressedOnce = sync.OnceFunc(func() { + log.Info(`Some vulnerabilities have been ignored/suppressed. Use the "--show-suppressed" flag to display them.`) + }) +) type vulnerabilityRenderer struct { w *bytes.Buffer @@ -73,6 +93,14 @@ func (r *vulnerabilityRenderer) Render() string { } func (r *vulnerabilityRenderer) renderDetectedVulnerabilities() { + // Show VEX notice only on CI + showVEXNoticeOnce.Do(func() { + if os.Getenv(envDisableNotice) != "" || os.Getenv("CI") == "" { + return + } + _, _ = color.New(color.FgCyan).Fprintf(r.w, vexNotice, doc.URL("docs/supply-chain/vex/repo", "publishing-vex-documents")) + }) + tw := newTableWriter(r.w, r.isTerminal) r.setHeaders(tw) r.setVulnerabilityRows(tw, r.result.Vulnerabilities)