Skip to content
6 changes: 6 additions & 0 deletions vulnfeeds/conversion/cve5/extraction.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ func GetVersionExtractor(cna string) VersionExtractor {
switch cna {
case "Linux":
return &LinuxVersionExtractor{}
case "Wordfence":
return &WordpressExtractor{Handler: &WordfenceHandler{}}
case "Patchstack":
return &WordpressExtractor{Handler: &PatchstackHandler{}}
case "WPScan":
return &WordpressExtractor{Handler: &WPScanHandler{}}
default:
return &DefaultVersionExtractor{}
}
Expand Down
14 changes: 13 additions & 1 deletion vulnfeeds/conversion/cve5/strategies.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,19 @@ func initialNormalExtraction(vers models.Versions, metrics *models.ConversionMet
introduced = vers.Version
metrics.AddNote("%s - Introduced from version value - %s", vQuality.String(), vers.Version)
}
if vLessThanQual.AtLeast(acceptableQuality) {
// Prefer changes for fixed version if available.
var fixedFromChanges string
for _, ch := range vers.Changes {
if ch.Status == "unaffected" && ch.At != "" {
fixedFromChanges = ch.At
break
}
}

if fixedFromChanges != "" {
fixed = fixedFromChanges
metrics.AddNote("Fixed from changes - %s", fixed)
} else if vLessThanQual.AtLeast(acceptableQuality) {
fixed = vers.LessThan
metrics.AddNote("%s - Fixed from LessThan value - %s", vLessThanQual.String(), vers.LessThan)
} else if vLTOEQual.AtLeast(acceptableQuality) {
Expand Down
90 changes: 89 additions & 1 deletion vulnfeeds/conversion/cve5/version_extraction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,26 @@ func TestFindNormalAffectedRanges(t *testing.T) {
},
wantRangeType: VersionRangeTypeGit,
},
{
name: "changes preferred over lessThanOrEqual with filler version",
affected: models.Affected{
Versions: []models.Versions{
{
Status: "affected",
Version: "n/a",
LessThanOrEqual: "1.0.32",
Changes: []models.Change{
{At: "1.0.33", Status: "unaffected"},
},
VersionType: "custom",
},
},
},
wantRanges: []*osvschema.Range{
conversion.BuildVersionRange("0", "", "1.0.33"),
},
wantRangeType: VersionRangeTypeEcosystem,
},
}

for _, tt := range tests {
Expand Down Expand Up @@ -381,6 +401,15 @@ func TestGetVersionExtractor(t *testing.T) {
},
expectedType: reflect.TypeOf(&LinuxVersionExtractor{}),
},
{
name: "Wordfence CVE",
cve: models.CVE5{
Metadata: models.CVE5Metadata{
AssignerShortName: "Wordfence",
},
},
expectedType: reflect.TypeOf(&WordpressExtractor{}),
},
{
name: "Default CVE",
cve: models.CVE5{
Expand Down Expand Up @@ -593,13 +622,72 @@ func TestExtractVersions(t *testing.T) {
},
}},
},
{
name: "CVE-2026-1293",
cve: loadTestData(t, "CVE-2026-1293"),
cnaAssigner: "Wordfence",
repos: []string{},
expectedAffected: []*osvschema.Affected{{
Package: &osvschema.Package{
Ecosystem: "WordPress:Plugin",
Name: "wordpress-seo",
},
Ranges: []*osvschema.Range{{
Type: osvschema.Range_ECOSYSTEM,
Events: []*osvschema.Event{
{Introduced: "0"},
{LastAffected: "26.8"},
},
}},
}},
},
{
name: "CVE-2021-23209",
cve: loadTestData(t, "CVE-2021-23209"),
cnaAssigner: "Patchstack",
repos: []string{},
expectedAffected: []*osvschema.Affected{{
Package: &osvschema.Package{
Ecosystem: "WordPress:Plugin",
Name: "accelerated-mobile-pages",
},
Ranges: []*osvschema.Range{{
Type: osvschema.Range_ECOSYSTEM,
Events: []*osvschema.Event{
{Introduced: "0"},
{Fixed: "1.0.77.33"},
},
}},
}},
},
{
name: "CVE-2015-10001",
cve: loadTestData(t, "CVE-2015-10001"),
cnaAssigner: "WPScan",
repos: []string{},
expectedAffected: []*osvschema.Affected{{
Package: &osvschema.Package{
Ecosystem: "WordPress:Plugin",
Name: "wp-stats",
},
Ranges: []*osvschema.Range{{
Type: osvschema.Range_ECOSYSTEM,
Events: []*osvschema.Event{
{Introduced: "2.52"},
{LastAffected: "2.52"},
},
}},
}},
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
metrics := &models.ConversionMetrics{}
v := vulns.Vulnerability{
Vulnerability: &osvschema.Vulnerability{},
Vulnerability: &osvschema.Vulnerability{
References: vulns.ClassifyReferences(identifyPossibleURLs(tc.cve)),
},
}
extractor := GetVersionExtractor(tc.cnaAssigner)
extractor.ExtractVersions(tc.cve, &v, metrics, tc.repos)
Expand Down
Loading
Loading