Skip to content

Commit eb1c929

Browse files
authored
fix(vulnfeeds): Deduplicate references with ReferenceType priority (#4934)
Updated logic to deduplicate references by their URL. A priority map is defined to make sure we keep the most useful reference type. The priority: FIX INTRODUCED DETECTION REPORT PACKAGE EVIDENCE ADVISORY ARTICLE DISCUSSION WEB GIT
1 parent 9d246b4 commit eb1c929

5 files changed

Lines changed: 95 additions & 36 deletions

File tree

vulnfeeds/cvelist2osv/__snapshots__/converter_test.snap

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,6 @@
7474
"type": "REPORT",
7575
"url": "https://hackerone.com/reports/2972576"
7676
},
77-
{
78-
"type": "ARTICLE",
79-
"url": "https://hackerone.com/reports/2972576"
80-
},
81-
{
82-
"type": "EVIDENCE",
83-
"url": "https://hackerone.com/reports/2972576"
84-
},
8577
{
8678
"type": "ADVISORY",
8779
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-1110"

vulnfeeds/cvelist2osv/converter_test.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -238,8 +238,6 @@ func TestFromCVE5(t *testing.T) {
238238
},
239239
},
240240
References: []*osvschema.Reference{
241-
{Type: osvschema.Reference_ARTICLE, Url: "https://hackerone.com/reports/2972576"},
242-
{Type: osvschema.Reference_EVIDENCE, Url: "https://hackerone.com/reports/2972576"},
243241
{Type: osvschema.Reference_REPORT, Url: "https://hackerone.com/reports/2972576"},
244242
{Type: osvschema.Reference_REPORT, Url: "https://gitlab.com/gitlab-org/gitlab/-/issues/517693"},
245243
},

vulnfeeds/cves/testdata/TestReposFromReferences_A_CVE_with_a_repo_that_redirects_(docker_docker_-__moby_moby).yaml

Lines changed: 54 additions & 0 deletions
Large diffs are not rendered by default.

vulnfeeds/vulns/vulns.go

Lines changed: 41 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,24 @@ const (
8282
Filler // Has been determined to be a filler word
8383
)
8484

85+
// refTypePriority is a read-only map ReferenceType to priority.
86+
// When multiple references are associated with the same URL, we deduplicate and only keep the type with the highest priority.
87+
// Priority (highest to lowest):
88+
// FIX > INTRODUCED > DETECTION > REPORT > PACKAGE > EVIDENCE > ADVISORY > ARTICLE > DISCUSSION > WEB > GIT
89+
var refTypePriority = map[osvschema.Reference_Type]int{
90+
osvschema.Reference_FIX: 11,
91+
osvschema.Reference_INTRODUCED: 10,
92+
osvschema.Reference_DETECTION: 9,
93+
osvschema.Reference_REPORT: 8,
94+
osvschema.Reference_PACKAGE: 7,
95+
osvschema.Reference_EVIDENCE: 6,
96+
osvschema.Reference_ADVISORY: 5,
97+
osvschema.Reference_ARTICLE: 4,
98+
osvschema.Reference_DISCUSSION: 3,
99+
osvschema.Reference_WEB: 2,
100+
osvschema.Reference_GIT: 1,
101+
}
102+
85103
// AttachExtractedVersionInfo converts the models.VersionInfo struct to OSV GIT and ECOSYSTEM AffectedRanges and AffectedPackage.
86104
func AttachExtractedVersionInfo(v *Vulnerability, version models.VersionInfo) {
87105
// commit holds a commit hash of one of the supported commit types.
@@ -662,37 +680,36 @@ func Unique[T comparable](s []T) []T {
662680
}
663681

664682
// ClassifyReferences annotates reference links based on their tags or their shape.
683+
// References with the same URL are deduplicated, and only keep the RefType of the highest priority (see refTypePriority).
665684
func ClassifyReferences(refs []models.Reference) []*osvschema.Reference {
666-
var references []*osvschema.Reference
667-
refMap := make(map[string]map[osvschema.Reference_Type]bool)
668-
669-
for _, reference := range refs {
670-
if _, ok := refMap[reference.URL]; !ok {
671-
refMap[reference.URL] = make(map[osvschema.Reference_Type]bool)
672-
}
673-
674-
if len(reference.Tags) > 0 {
675-
for _, tag := range reference.Tags {
676-
refType := ClassifyReferenceLink(reference.URL, tag)
677-
if !refMap[reference.URL][refType] {
678-
references = append(references, &osvschema.Reference{
679-
Type: refType,
680-
Url: reference.URL,
681-
})
682-
refMap[reference.URL][refType] = true
685+
references := make([]*osvschema.Reference, 0, len(refs))
686+
bestTypes := make(map[string]osvschema.Reference_Type)
687+
688+
for _, ref := range refs {
689+
if len(ref.Tags) > 0 {
690+
for _, tag := range ref.Tags {
691+
refType := ClassifyReferenceLink(ref.URL, tag)
692+
bestType, ok := bestTypes[ref.URL]
693+
if !ok || refTypePriority[refType] > refTypePriority[bestType] {
694+
bestTypes[ref.URL] = refType
683695
}
684696
}
685697
} else {
686-
refType := ClassifyReferenceLink(reference.URL, "")
687-
if !refMap[reference.URL][refType] {
688-
references = append(references, &osvschema.Reference{
689-
Type: refType,
690-
Url: reference.URL,
691-
})
692-
refMap[reference.URL][refType] = true
698+
refType := ClassifyReferenceLink(ref.URL, "")
699+
bestType, ok := bestTypes[ref.URL]
700+
if !ok || refTypePriority[refType] > refTypePriority[bestType] {
701+
bestTypes[ref.URL] = refType
693702
}
694703
}
695704
}
705+
706+
for refURL, refType := range bestTypes {
707+
references = append(references, &osvschema.Reference{
708+
Type: refType,
709+
Url: refURL,
710+
})
711+
}
712+
696713
sort.SliceStable(references, func(i, j int) bool {
697714
return references[i].GetType() < references[j].GetType()
698715
})

vulnfeeds/vulns/vulns_test.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,6 @@ func TestClassifyReferences(t *testing.T) {
106106
},
107107
},
108108
references: []*osvschema.Reference{
109-
{Url: "https://github.com/curl/curl/issues/9271", Type: osvschema.Reference_ADVISORY},
110-
{Url: "https://github.com/curl/curl/issues/9271", Type: osvschema.Reference_EVIDENCE},
111109
{Url: "https://github.com/curl/curl/issues/9271", Type: osvschema.Reference_REPORT},
112110
},
113111
},

0 commit comments

Comments
 (0)