From 8258c59042371b75a16474205dc7c3256759c067 Mon Sep 17 00:00:00 2001 From: knqyf263 Date: Mon, 1 Apr 2024 16:50:00 +0400 Subject: [PATCH] refactor Signed-off-by: knqyf263 --- pkg/vulnsrc/ghsa/ghsa.go | 65 ++++++++++++++++++++-------------------- pkg/vulnsrc/osv/osv.go | 8 +++-- 2 files changed, 38 insertions(+), 35 deletions(-) diff --git a/pkg/vulnsrc/ghsa/ghsa.go b/pkg/vulnsrc/ghsa/ghsa.go index 50a56bca..be67dfee 100644 --- a/pkg/vulnsrc/ghsa/ghsa.go +++ b/pkg/vulnsrc/ghsa/ghsa.go @@ -94,42 +94,14 @@ func (t *transformer) TransformAdvisories(advisories []osv.Advisory, entry osv.E return nil, xerrors.Errorf("JSON decode error: %w", err) } - severity := convertSeverity(specific.Severity) for i, adv := range advisories { - // Add version from `last_known_affected_version_range` field. - // cf. https://github.com/github/advisory-database/issues/470#issuecomment-1998604377 - for _, entryAffected := range entry.Affected { - // Skip if `affected[].database_specific` field doesn't exist - if entryAffected.DatabaseSpecific == nil { - continue - } - - var affectedSpecific DatabaseSpecific - if err := json.Unmarshal(entryAffected.DatabaseSpecific, &affectedSpecific); err != nil { - return nil, xerrors.Errorf("JSON decode error: %w", err) - } - - entryEcosystem := osv.ConvertEcosystem(entryAffected.Package.Ecosystem) - entryPkgName := vulnerability.NormalizePkgName(entryEcosystem, entryAffected.Package.Name) - - if adv.PkgName != entryPkgName || adv.Ecosystem != entryEcosystem { - continue - } - - for j, vulnVersion := range adv.VulnerableVersions { - // `fixed` and `last_affected` fields (`<`,`<=` or `=` is used) have high priority then `last_known_affected_version_range`. - if strings.Contains(vulnVersion, "<") || strings.HasPrefix(vulnVersion, "=") { - continue - } - - // `last_known_affected_version_range` uses `< version` or `<= version` formats (e.g. `< 1.2.3` or `<= 1.2.3`). - // Remove space to fit our format. - affectedSpecific.LastKnownAffectedVersionRange = strings.ReplaceAll(affectedSpecific.LastKnownAffectedVersionRange, " ", "") - advisories[i].VulnerableVersions[j] = fmt.Sprintf("%s, %s", vulnVersion, affectedSpecific.LastKnownAffectedVersionRange) - } + // Parse database_specific + if err := parseDatabaseSpecific(adv); err != nil { + return nil, xerrors.Errorf("failed to parse database specific: %w", err) } - // Fill severity from + // Fill severity from GHSA + severity := convertSeverity(specific.Severity) advisories[i].Severity = severity // Replace a git URL with a CocoaPods package name in a Swift vulnerability @@ -147,6 +119,33 @@ func (t *transformer) TransformAdvisories(advisories []osv.Advisory, entry osv.E return advisories, nil } +// parseDatabaseSpecific adds a version from the last_known_affected_version_range field +// cf. https://github.com/github/advisory-database/issues/470#issuecomment-1998604377 +func parseDatabaseSpecific(advisory osv.Advisory) error { + // Skip if the `affected[].database_specific` field doesn't exist + if advisory.DatabaseSpecific == nil { + return nil + } + + var affectedSpecific DatabaseSpecific + if err := json.Unmarshal(advisory.DatabaseSpecific, &affectedSpecific); err != nil { + return xerrors.Errorf("JSON decode error: %w", err) + } + + for i, vulnVersion := range advisory.VulnerableVersions { + // The fixed and last_affected fields (which use <, <=, or =) take precedence over + // the last_known_affected_version_range field. + if strings.Contains(vulnVersion, "<") || strings.HasPrefix(vulnVersion, "=") { + continue + } + // `last_known_affected_version_range` uses `< version` or `<= version` formats (e.g. `< 1.2.3` or `<= 1.2.3`). + // Remove spaces to match our format + verRange := strings.ReplaceAll(affectedSpecific.LastKnownAffectedVersionRange, " ", "") + advisory.VulnerableVersions[i] = fmt.Sprintf("%s, %s", vulnVersion, verRange) + } + return nil +} + func convertSeverity(severity string) types.Severity { switch severity { case "LOW": diff --git a/pkg/vulnsrc/osv/osv.go b/pkg/vulnsrc/osv/osv.go index da6ea824..6bd03258 100644 --- a/pkg/vulnsrc/osv/osv.go +++ b/pkg/vulnsrc/osv/osv.go @@ -40,6 +40,9 @@ type Advisory struct { References []string CVSSScoreV3 float64 CVSSVectorV3 string + + // From affected[].database_specific + DatabaseSpecific json.RawMessage } type OSV struct { @@ -212,7 +215,7 @@ func parseAffected(entry Entry, vulnIDs, aliases, references []string) ([]Adviso uniqAdvisories := map[string]Advisory{} for _, affected := range entry.Affected { - ecosystem := ConvertEcosystem(affected.Package.Ecosystem) + ecosystem := convertEcosystem(affected.Package.Ecosystem) if ecosystem == vulnerability.Unknown { continue } @@ -252,6 +255,7 @@ func parseAffected(entry Entry, vulnIDs, aliases, references []string) ([]Adviso References: references, CVSSVectorV3: cvssVectorV3, CVSSScoreV3: cvssScoreV3, + DatabaseSpecific: affected.DatabaseSpecific, } } } @@ -334,7 +338,7 @@ func parseSeverity(severities []Severity) (string, float64, error) { return "", 0, nil } -func ConvertEcosystem(eco Ecosystem) types.Ecosystem { +func convertEcosystem(eco Ecosystem) types.Ecosystem { // cf. https://ossf.github.io/osv-schema/#affectedpackage-field switch strings.ToLower(string(eco)) { case "go":