package vulnerability import ( "bufio" "os" "sort" "strings" "github.com/google/wire" "github.com/aquasecurity/trivy-db/pkg/db" dbTypes "github.com/aquasecurity/trivy-db/pkg/types" "github.com/aquasecurity/trivy/pkg/log" "github.com/aquasecurity/trivy/pkg/types" "github.com/aquasecurity/trivy/pkg/utils" ) const ( DefaultIgnoreFile = ".trivyignore" ) var SuperSet = wire.NewSet( wire.Struct(new(db.Config)), NewClient, wire.Bind(new(Operation), new(Client)), ) type Operation interface { FillInfo(vulns []types.DetectedVulnerability, light bool) Filter(vulns []types.DetectedVulnerability, severities []dbTypes.Severity, ignoreUnfixed bool, ignoreFile string) []types.DetectedVulnerability } type Client struct { dbc db.Operation } func NewClient(dbc db.Config) Client { return Client{dbc: dbc} } func (c Client) FillInfo(vulns []types.DetectedVulnerability, light bool) { var err error var severity dbTypes.Severity for i := range vulns { if light { severity, err = c.dbc.GetSeverity(vulns[i].VulnerabilityID) vulns[i].Vulnerability.Severity = severity.String() } else { vulns[i].Vulnerability, err = c.dbc.GetVulnerability(vulns[i].VulnerabilityID) } if err != nil { log.Logger.Warnf("Error while getting vulnerability details: %s\n", err) continue } } } func (c Client) Filter(vulns []types.DetectedVulnerability, severities []dbTypes.Severity, ignoreUnfixed bool, ignoreFile string) []types.DetectedVulnerability { ignoredIDs := getIgnoredIDs(ignoreFile) var vulnerabilities []types.DetectedVulnerability for _, vuln := range vulns { // Filter vulnerabilities by severity for _, s := range severities { if s.String() == vuln.Severity { // Ignore unfixed vulnerabilities if ignoreUnfixed && vuln.FixedVersion == "" { continue } else if utils.StringInSlice(vuln.VulnerabilityID, ignoredIDs) { continue } vulnerabilities = append(vulnerabilities, vuln) break } } } sort.Slice(vulnerabilities, func(i, j int) bool { if vulnerabilities[i].PkgName != vulnerabilities[j].PkgName { return vulnerabilities[i].PkgName < vulnerabilities[j].PkgName } ret := dbTypes.CompareSeverityString( vulnerabilities[j].Severity, vulnerabilities[i].Severity, ) if ret != 0 { return ret > 0 } return vulnerabilities[i].VulnerabilityID < vulnerabilities[j].VulnerabilityID }) return vulnerabilities } func getIgnoredIDs(ignoreFile string) []string { f, err := os.Open(ignoreFile) if err != nil { // trivy must work even if no .trivyignore exist return nil } var ignoredIDs []string scanner := bufio.NewScanner(f) for scanner.Scan() { line := scanner.Text() line = strings.TrimSpace(line) if strings.HasPrefix(line, "#") || line == "" { continue } ignoredIDs = append(ignoredIDs, line) } return ignoredIDs }