diff --git a/vulnfeeds/conversion/common.go b/vulnfeeds/conversion/common.go index 3c58edbead8..250424ccf1f 100644 --- a/vulnfeeds/conversion/common.go +++ b/vulnfeeds/conversion/common.go @@ -743,7 +743,20 @@ func ProcessRanges(ranges []models.RangeWithMetadata, repos []string, metrics *m if len(un) > 0 { metrics.UnresolvedRangesCount += len(un) if len(r) == 0 { - metrics.SetOutcome(models.NoCommitRanges) + hasRepo := len(repos) > 0 + if !hasRepo { + for _, ra := range ranges { + if ra.Range.GetRepo() != "" { + hasRepo = true + break + } + } + } + if !hasRepo { + metrics.SetOutcome(models.NoRepos) + } else { + metrics.SetOutcome(models.NoCommitRanges) + } } } diff --git a/vulnfeeds/conversion/cve5/extraction.go b/vulnfeeds/conversion/cve5/extraction.go index ab6854dbb2c..2c43d61f986 100644 --- a/vulnfeeds/conversion/cve5/extraction.go +++ b/vulnfeeds/conversion/cve5/extraction.go @@ -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{} } diff --git a/vulnfeeds/conversion/cve5/strategies.go b/vulnfeeds/conversion/cve5/strategies.go index 5a6de90fb6c..389bfe8b9d4 100644 --- a/vulnfeeds/conversion/cve5/strategies.go +++ b/vulnfeeds/conversion/cve5/strategies.go @@ -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) { diff --git a/vulnfeeds/conversion/cve5/version_extraction_test.go b/vulnfeeds/conversion/cve5/version_extraction_test.go index 746da9be8f9..622331f11ff 100644 --- a/vulnfeeds/conversion/cve5/version_extraction_test.go +++ b/vulnfeeds/conversion/cve5/version_extraction_test.go @@ -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 { @@ -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{ @@ -593,13 +622,60 @@ 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: nil, + }, } 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) diff --git a/vulnfeeds/conversion/cve5/wordpress.go b/vulnfeeds/conversion/cve5/wordpress.go new file mode 100644 index 00000000000..22a5cad1507 --- /dev/null +++ b/vulnfeeds/conversion/cve5/wordpress.go @@ -0,0 +1,359 @@ +package cve5 + +import ( + "regexp" + "slices" + "strings" + + c "github.com/google/osv.dev/vulnfeeds/conversion" + "github.com/google/osv.dev/vulnfeeds/models" + "github.com/google/osv.dev/vulnfeeds/vulns" + "github.com/ossf/osv-schema/bindings/go/osvschema" +) + +var ( + wpPluginTracRegex = regexp.MustCompile(`plugins\.trac\.wordpress\.org/browser/([^/]+)`) + wpPluginSvnRegex = regexp.MustCompile(`plugins\.svn\.wordpress\.org/([^/]+)`) + wpPluginOrgRegex = regexp.MustCompile(`wordpress\.org/plugins/([^/]+)`) + wpThemeTracRegex = regexp.MustCompile(`themes\.trac\.wordpress\.org/browser/([^/]+)`) + wpThemeSvnRegex = regexp.MustCompile(`themes\.svn\.wordpress\.org/([^/]+)`) + wpThemeOrgRegex = regexp.MustCompile(`wordpress\.org/themes/([^/]+)`) + + wordfencePluginRegex = regexp.MustCompile(`wordfence\.com/threat-intel/vulnerabilities/wordpress-plugins/([^/]+)`) + wordfenceThemeRegex = regexp.MustCompile(`wordfence\.com/threat-intel/vulnerabilities/wordpress-themes/([^/]+)`) + + patchstackVulnRegex = regexp.MustCompile(`patchstack\.com/database/vulnerability/([^/]+)`) + patchstackPluginRegex = regexp.MustCompile(`patchstack\.com/database/wordpress/plugin/([^/]+)`) + patchstackThemeRegex = regexp.MustCompile(`patchstack\.com/database/wordpress/theme/([^/]+)`) +) + +// extractWordPressSlugAndEcosystem unifies the logic to extract the slug and determine +// the specific WordPress ecosystem (Core, Plugin, Theme) for a given CVE. +func extractWordPressSlugAndEcosystem(cve models.CVE5, v *vulns.Vulnerability) (string, string) { + var slug string + var ecosystem = "WordPress" // Default/Fallback + + // 1. Core Check (Highest Priority) + if len(cve.Containers.CNA.Affected) > 0 { + aff := cve.Containers.CNA.Affected[0] + if strings.EqualFold(aff.Vendor, "wordpress") && strings.EqualFold(aff.Product, "wordpress") { + return "wordpress", "WordPress:Core" + } + } + + // 2. Ecosystem Extraction from CollectionURL + if len(cve.Containers.CNA.Affected) > 0 { + aff := cve.Containers.CNA.Affected[0] + switch aff.CollectionURL { + case "https://wordpress.org/themes": + ecosystem = "WordPress:Theme" + case "https://wordpress.org/plugins": + ecosystem = "WordPress:Plugin" + } + } + + // 3. Extract slug and ecosystem from Reference URLs + var tracSlug, svnSlug, wordfenceSlug, wpOrgPluginSlug, wpOrgThemeSlug, patchstackPluginSlug, patchstackThemeSlug, patchstackVulnSlug string + var urlEcosystem string + + for _, ref := range v.References { + url := ref.GetUrl() + + if match := wpPluginTracRegex.FindStringSubmatch(url); match != nil { + tracSlug = match[1] + if urlEcosystem == "" { + urlEcosystem = "WordPress:Plugin" + } + } else if match := wpPluginSvnRegex.FindStringSubmatch(url); match != nil { + svnSlug = match[1] + if urlEcosystem == "" { + urlEcosystem = "WordPress:Plugin" + } + } else if match := wpThemeTracRegex.FindStringSubmatch(url); match != nil { + tracSlug = match[1] + if urlEcosystem == "" { + urlEcosystem = "WordPress:Theme" + } + } else if match := wpThemeSvnRegex.FindStringSubmatch(url); match != nil { + svnSlug = match[1] + if urlEcosystem == "" { + urlEcosystem = "WordPress:Theme" + } + } else if match := wordfencePluginRegex.FindStringSubmatch(url); match != nil { + wordfenceSlug = match[1] + if urlEcosystem == "" { + urlEcosystem = "WordPress:Plugin" + } + } else if match := wordfenceThemeRegex.FindStringSubmatch(url); match != nil { + wordfenceSlug = match[1] + if urlEcosystem == "" { + urlEcosystem = "WordPress:Theme" + } + } else if match := wpPluginOrgRegex.FindStringSubmatch(url); match != nil { + wpOrgPluginSlug = match[1] + if urlEcosystem == "" { + urlEcosystem = "WordPress:Plugin" + } + } else if match := wpThemeOrgRegex.FindStringSubmatch(url); match != nil { + wpOrgThemeSlug = match[1] + if urlEcosystem == "" { + urlEcosystem = "WordPress:Theme" + } + } else if match := patchstackPluginRegex.FindStringSubmatch(url); match != nil { + patchstackPluginSlug = match[1] + if urlEcosystem == "" { + urlEcosystem = "WordPress:Plugin" + } + } else if match := patchstackThemeRegex.FindStringSubmatch(url); match != nil { + patchstackThemeSlug = match[1] + if urlEcosystem == "" { + urlEcosystem = "WordPress:Theme" + } + } else if match := patchstackVulnRegex.FindStringSubmatch(url); match != nil { + patchstackVulnSlug = match[1] + } + + // Generic URL keyword check for ecosystem if still generic + if urlEcosystem == "" { + if strings.Contains(url, "/theme/") || strings.Contains(url, "/themes/") { + urlEcosystem = "WordPress:Theme" + } else if strings.Contains(url, "/plugin/") || strings.Contains(url, "/plugins/") { + urlEcosystem = "WordPress:Plugin" + } + } + } + + slugsToTry := []string{ + tracSlug, + svnSlug, + wordfenceSlug, + wpOrgPluginSlug, + wpOrgThemeSlug, + patchstackPluginSlug, + patchstackThemeSlug, + patchstackVulnSlug, + } + + for _, s := range slugsToTry { + if s != "" { + slug = s + break + } + } + + if ecosystem == "WordPress" && urlEcosystem != "" { + ecosystem = urlEcosystem + } + + // 4. Description/Title Heuristics Fallback for ecosystem + if ecosystem == "WordPress" { + desc := strings.ToLower(models.EnglishDescription(cve.Containers.CNA.Descriptions)) + title := strings.ToLower(cve.Containers.CNA.Title) + + if strings.Contains(desc, "plugin") || strings.Contains(title, "plugin") { + ecosystem = "WordPress:Plugin" + } else if strings.Contains(desc, "theme") || strings.Contains(title, "theme") { + ecosystem = "WordPress:Theme" + } + } + + return slug, ecosystem +} + +// WordpressHandler defines hooks for CNA-specific logic. +type WordpressHandler interface { + PreExtract(cve *models.CVE5) + PostExtractDefault(v *vulns.Vulnerability, metrics *models.ConversionMetrics, slug string, ecosystem string) +} + +// WordpressExtractor handles version extraction for WordPress CVEs. +type WordpressExtractor struct { + DefaultVersionExtractor + + Handler WordpressHandler +} + +var _ VersionExtractor = &WordpressExtractor{} + +func (w *WordpressExtractor) ExtractVersions(cve models.CVE5, v *vulns.Vulnerability, metrics *models.ConversionMetrics, repos []string) { + if w.Handler != nil { + w.Handler.PreExtract(&cve) + } + + // 1. Run default extraction first + w.DefaultVersionExtractor.ExtractVersions(cve, v, metrics, repos) + + // 2. Extract slug and determine ecosystem using shared helper + slug, ecosystem := extractWordPressSlugAndEcosystem(cve, v) + + if w.Handler != nil { + w.Handler.PostExtractDefault(v, metrics, slug, ecosystem) + } + + // 3. Update affected packages with correct ecosystem and slug + if len(v.Affected) > 0 { + for _, aff := range v.Affected { + isGit := false + for _, r := range aff.GetRanges() { + if r.GetType() == osvschema.Range_GIT { + isGit = true + break + } + } + if isGit { + aff.Package = nil // Do not put package info on GIT ranges + continue + } + + if slug == "" { + continue // Skip enriching if we have no slug + } + + if aff.GetPackage() == nil { + aff.Package = &osvschema.Package{ + Ecosystem: ecosystem, + Name: slug, + } + } else { + // Update ecosystem if it was generic + if aff.GetPackage().GetEcosystem() == "WordPress" || aff.GetPackage().GetEcosystem() == "" { + aff.Package.Ecosystem = ecosystem + } + if aff.GetPackage().GetName() == "" { + aff.Package.Name = slug + } + } + } + } + + // 4. Unified Fallback Strategy + if len(v.Affected) == 0 { + if slug == "" { + metrics.AddNote("Failed to extract versions via default, and no WordPress slug found to attempt fallback") + if len(repos) == 0 { + metrics.Outcome = models.NoRepos + } + + return + } + + metrics.AddNote("Attempting to generate ECOSYSTEM ranges for WordPress") + + gotVersions := false + var allRanges []*osvschema.Range + + // Fallback 1: CNA Affected + for _, cveAff := range cve.Containers.CNA.Affected { + versionRanges, _ := w.FindNormalAffectedRanges(cveAff, metrics) + for _, r := range versionRanges { + r.Range.Type = osvschema.Range_ECOSYSTEM + allRanges = append(allRanges, r.Range) + } + } + + if len(allRanges) > 0 { + gotVersions = true + metrics.AddSource(models.VersionSourceAffected) + } + + // Fallback 2: CPE + if !gotVersions { + versionRanges, _ := cpeVersionExtraction(cve, metrics) + for _, r := range versionRanges { + r.Range.Type = osvschema.Range_ECOSYSTEM + allRanges = append(allRanges, r.Range) + } + if len(allRanges) > 0 { + gotVersions = true + } + } + + // Fallback 3: Description + if !gotVersions { + textRanges := c.ExtractVersionsFromText(nil, models.EnglishDescription(cve.Containers.CNA.Descriptions), metrics, models.VersionSourceDescription) + for _, r := range textRanges { + r.Range.Type = osvschema.Range_ECOSYSTEM + allRanges = append(allRanges, r.Range) + } + if len(allRanges) > 0 { + gotVersions = true + } + } + + if gotVersions { + aff := &osvschema.Affected{ + Package: &osvschema.Package{ + Ecosystem: ecosystem, + Name: slug, + }, + Ranges: allRanges, + } + c.AddAffected(v, aff, metrics) + metrics.Outcome = models.Successful // Override outcome directly + } + } +} + +// DefaultWordpressHandler provides empty implementations for the hooks. +type DefaultWordpressHandler struct{} + +func (d *DefaultWordpressHandler) PreExtract(_ *models.CVE5) {} +func (d *DefaultWordpressHandler) PostExtractDefault(_ *vulns.Vulnerability, _ *models.ConversionMetrics, _ string, _ string) { +} + +// WordfenceHandler implements Wordfence specific quirks. +type WordfenceHandler struct { + DefaultWordpressHandler +} + +func normalizeVersion(v string) string { + return strings.TrimPrefix(v, "v") +} + +func (w *WordfenceHandler) PreExtract(cve *models.CVE5) { + for i := range cve.Containers.CNA.Affected { + for j := range cve.Containers.CNA.Affected[i].Versions { + vers := &cve.Containers.CNA.Affected[i].Versions[j] + vers.Version = normalizeVersion(vers.Version) + vers.LessThan = normalizeVersion(vers.LessThan) + vers.LessThanOrEqual = normalizeVersion(vers.LessThanOrEqual) + } + } +} + +// PatchstackHandler implements Patchstack specific quirks. +type PatchstackHandler struct { + DefaultWordpressHandler +} + +func (p *PatchstackHandler) PostExtractDefault(v *vulns.Vulnerability, metrics *models.ConversionMetrics, slug string, ecosystem string) { + if slug != "" { + var baseURL string + switch ecosystem { + case "WordPress:Plugin": + baseURL = "https://wordpress.org/plugins/" + case "WordPress:Theme": + baseURL = "https://wordpress.org/themes/" + } + + if baseURL != "" { + wpURL := baseURL + slug + "/" + // Check if already exists to avoid duplicates + exists := slices.ContainsFunc(v.References, func(ref *osvschema.Reference) bool { + return ref.GetUrl() == wpURL + }) + if !exists { + v.References = append(v.References, &osvschema.Reference{ + Type: osvschema.Reference_WEB, + Url: wpURL, + }) + metrics.AddNote("Added wordpress.org reference link: %s", wpURL) + } + } + } +} + +// WPScanHandler implements WPScan specific quirks. +type WPScanHandler struct { + DefaultWordpressHandler +} diff --git a/vulnfeeds/models/cve.go b/vulnfeeds/models/cve.go index cb5635eecd5..89c45f66cf0 100644 --- a/vulnfeeds/models/cve.go +++ b/vulnfeeds/models/cve.go @@ -127,12 +127,18 @@ type Affected struct { DefaultStatus string `json:"defaultStatus,omitempty"` } +type Change struct { + At string `json:"at,omitempty"` + Status string `json:"status,omitempty"` +} + type Versions struct { - Version string `json:"version,omitempty"` - Status string `json:"status,omitempty"` - LessThanOrEqual string `json:"lessThanOrEqual,omitempty"` - LessThan string `json:"lessThan,omitempty"` - VersionType string `json:"versionType,omitempty"` + Version string `json:"version,omitempty"` + Status string `json:"status,omitempty"` + LessThanOrEqual string `json:"lessThanOrEqual,omitempty"` + LessThan string `json:"lessThan,omitempty"` + VersionType string `json:"versionType,omitempty"` + Changes []Change `json:"changes,omitempty"` } type CVE5 struct { diff --git a/vulnfeeds/test_data/cvelistV5/cves/2015/10xxx/CVE-2015-10001.json b/vulnfeeds/test_data/cvelistV5/cves/2015/10xxx/CVE-2015-10001.json new file mode 100644 index 00000000000..400644c2eab --- /dev/null +++ b/vulnfeeds/test_data/cvelistV5/cves/2015/10xxx/CVE-2015-10001.json @@ -0,0 +1,185 @@ +{ + "containers": { + "cna": { + "affected": [ + { + "product": "WP-Stats", + "vendor": "Unknown", + "versions": [ + { + "lessThan": "2.52", + "status": "affected", + "version": "2.52", + "versionType": "custom" + } + ] + } + ], + "credits": [ + { + "lang": "en", + "value": "Sebastian Wolfgang Kraemer" + } + ], + "descriptions": [ + { + "lang": "en", + "value": "The WP-Stats WordPress plugin before 2.52 does not have CSRF check when saving its settings, and did not escape some of them when outputting them, allowing attacker to make logged in high privilege users change them and set Cross-Site Scripting payloads" + } + ], + "problemTypes": [ + { + "descriptions": [ + { + "cweId": "CWE-352", + "description": "CWE-352 Cross-Site Request Forgery (CSRF)", + "lang": "en", + "type": "CWE" + } + ] + } + ], + "providerMetadata": { + "dateUpdated": "2021-11-01T08:45:47.000Z", + "orgId": "1bfdd5d7-9bf6-4a53-96ea-42e2716d7a81", + "shortName": "WPScan" + }, + "references": [ + { + "tags": [ + "x_refsource_MISC" + ], + "url": "https://wpscan.com/vulnerability/f5c3dfea-7203-4a98-88ff-aa6a24d03734" + }, + { + "tags": [ + "x_refsource_MISC" + ], + "url": "https://www.openwall.com/lists/oss-security/2015/06/17/6" + } + ], + "source": { + "discovery": "EXTERNAL" + }, + "title": "WP-Stats < 2.5.2 - CSRF to Stored Cross-Site Scripting (XSS)", + "x_generator": "WPScan CVE Generator", + "x_legacyV4Record": { + "CVE_data_meta": { + "ASSIGNER": "contact@wpscan.com", + "ID": "CVE-2015-10001", + "STATE": "PUBLIC", + "TITLE": "WP-Stats < 2.5.2 - CSRF to Stored Cross-Site Scripting (XSS)" + }, + "affects": { + "vendor": { + "vendor_data": [ + { + "product": { + "product_data": [ + { + "product_name": "WP-Stats", + "version": { + "version_data": [ + { + "version_affected": "<", + "version_name": "2.52", + "version_value": "2.52" + } + ] + } + } + ] + }, + "vendor_name": "Unknown" + } + ] + } + }, + "credit": [ + { + "lang": "eng", + "value": "Sebastian Wolfgang Kraemer" + } + ], + "data_format": "MITRE", + "data_type": "CVE", + "data_version": "4.0", + "description": { + "description_data": [ + { + "lang": "eng", + "value": "The WP-Stats WordPress plugin before 2.52 does not have CSRF check when saving its settings, and did not escape some of them when outputting them, allowing attacker to make logged in high privilege users change them and set Cross-Site Scripting payloads" + } + ] + }, + "generator": "WPScan CVE Generator", + "problemtype": { + "problemtype_data": [ + { + "description": [ + { + "lang": "eng", + "value": "CWE-352 Cross-Site Request Forgery (CSRF)" + } + ] + } + ] + }, + "references": { + "reference_data": [ + { + "name": "https://wpscan.com/vulnerability/f5c3dfea-7203-4a98-88ff-aa6a24d03734", + "refsource": "MISC", + "url": "https://wpscan.com/vulnerability/f5c3dfea-7203-4a98-88ff-aa6a24d03734" + }, + { + "name": "https://www.openwall.com/lists/oss-security/2015/06/17/6", + "refsource": "MISC", + "url": "https://www.openwall.com/lists/oss-security/2015/06/17/6" + } + ] + }, + "source": { + "discovery": "EXTERNAL" + } + } + }, + "adp": [ + { + "providerMetadata": { + "orgId": "af854a3a-2127-422b-91ae-364da2661108", + "shortName": "CVE", + "dateUpdated": "2024-08-06T08:58:24.557Z" + }, + "title": "CVE Program Container", + "references": [ + { + "tags": [ + "x_refsource_MISC", + "x_transferred" + ], + "url": "https://wpscan.com/vulnerability/f5c3dfea-7203-4a98-88ff-aa6a24d03734" + }, + { + "tags": [ + "x_refsource_MISC", + "x_transferred" + ], + "url": "https://www.openwall.com/lists/oss-security/2015/06/17/6" + } + ] + } + ] + }, + "cveMetadata": { + "assignerOrgId": "1bfdd5d7-9bf6-4a53-96ea-42e2716d7a81", + "assignerShortName": "WPScan", + "cveId": "CVE-2015-10001", + "datePublished": "2021-11-01T08:45:47.000Z", + "dateReserved": "2021-10-31T00:00:00.000Z", + "dateUpdated": "2024-08-06T08:58:24.557Z", + "state": "PUBLISHED" + }, + "dataType": "CVE_RECORD", + "dataVersion": "5.1" +} \ No newline at end of file diff --git a/vulnfeeds/test_data/cvelistV5/cves/2021/23xxx/CVE-2021-23209.json b/vulnfeeds/test_data/cvelistV5/cves/2021/23xxx/CVE-2021-23209.json new file mode 100644 index 00000000000..b7358d5cb5e --- /dev/null +++ b/vulnfeeds/test_data/cvelistV5/cves/2021/23xxx/CVE-2021-23209.json @@ -0,0 +1,299 @@ +{ + "containers": { + "cna": { + "affected": [ + { + "collectionURL": "https://wordpress.org/plugins", + "defaultStatus": "unaffected", + "packageName": "accelerated-mobile-pages", + "product": "AMP for WP – Accelerated Mobile Pages (WordPress plugin)", + "vendor": "Ahmed Kaludi, Mohammed Kaludi", + "versions": [ + { + "changes": [ + { + "at": "1.0.77.33", + "status": "unaffected" + } + ], + "lessThanOrEqual": "1.0.77.32", + "status": "affected", + "version": "n/a", + "versionType": "custom" + } + ] + } + ], + "credits": [ + { + "lang": "en", + "type": "finder", + "user": "00000000-0000-4000-9000-000000000000", + "value": "FearZzZz (Patchstack Alliance)" + } + ], + "datePublic": "2021-12-14T17:00:00.000Z", + "descriptions": [ + { + "lang": "en", + "supportingMedia": [ + { + "base64": false, + "type": "text/html", + "value": "

Multiple Authenticated (admin user role) Persistent Cross-Site Scripting (XSS) vulnerabilities discovered in AMP for WP – Accelerated Mobile Pages WordPress plugin (versions <= 1.0.77.32).

" + } + ], + "value": "Multiple Authenticated (admin user role) Persistent Cross-Site Scripting (XSS) vulnerabilities discovered in AMP for WP – Accelerated Mobile Pages WordPress plugin (versions <= 1.0.77.32)." + } + ], + "impacts": [ + { + "capecId": "CAPEC-592", + "descriptions": [ + { + "lang": "en", + "value": "CAPEC-592 Stored XSS" + } + ] + } + ], + "metrics": [ + { + "cvssV3_1": { + "attackComplexity": "LOW", + "attackVector": "NETWORK", + "availabilityImpact": "NONE", + "baseScore": 4.8, + "baseSeverity": "MEDIUM", + "confidentialityImpact": "LOW", + "integrityImpact": "LOW", + "privilegesRequired": "HIGH", + "scope": "CHANGED", + "userInteraction": "REQUIRED", + "vectorString": "CVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:C/C:L/I:L/A:N", + "version": "3.1" + }, + "format": "CVSS", + "scenarios": [ + { + "lang": "en", + "value": "GENERAL" + } + ] + } + ], + "problemTypes": [ + { + "descriptions": [ + { + "cweId": "CWE-79", + "description": "CWE-79 Cross-site Scripting (XSS)", + "lang": "en", + "type": "CWE" + } + ] + } + ], + "providerMetadata": { + "orgId": "21595511-bba5-4825-b968-b78d1f9984a3", + "shortName": "Patchstack", + "dateUpdated": "2026-04-28T16:07:30.318Z" + }, + "references": [ + { + "tags": [ + "vdb-entry" + ], + "url": "https://patchstack.com/database/vulnerability/accelerated-mobile-pages/wordpress-amp-for-wp-accelerated-mobile-pages-plugin-1-0-77-32-multiple-authenticated-persistent-cross-site-scripting-xss-vulnerabilities?_s_id=cve" + } + ], + "solutions": [ + { + "lang": "en", + "supportingMedia": [ + { + "base64": false, + "type": "text/html", + "value": "

Update to 1.0.77.33 or higher version.

" + } + ], + "value": "Update to 1.0.77.33 or higher version." + } + ], + "source": { + "discovery": "EXTERNAL" + }, + "title": "WordPress AMP for WP – Accelerated Mobile Pages plugin <= 1.0.77.32 - Multiple Auth. Stored Cross-Site Scripting (XSS) vulnerabilities", + "x_generator": { + "engine": "Vulnogram 0.0.9" + }, + "x_legacyV4Record": { + "CVE_data_meta": { + "ASSIGNER": "audit@patchstack.com", + "DATE_PUBLIC": "2021-12-15T10:11:00.000Z", + "ID": "CVE-2021-23209", + "STATE": "PUBLIC", + "TITLE": "WordPress AMP for WP – Accelerated Mobile Pages plugin <= 1.0.77.32 - Multiple Authenticated Persistent Cross-Site Scripting (XSS) vulnerabilities" + }, + "affects": { + "vendor": { + "vendor_data": [ + { + "product": { + "product_data": [ + { + "product_name": "AMP for WP – Accelerated Mobile Pages (WordPress plugin)", + "version": { + "version_data": [ + { + "version_affected": "<=", + "version_name": "<= 1.0.77.32", + "version_value": "1.0.77.32" + } + ] + } + } + ] + }, + "vendor_name": "Ahmed Kaludi, Mohammed Kaludi" + } + ] + } + }, + "credit": [ + { + "lang": "eng", + "value": "Vulnerability discovered by Ex.Mi (Patchstack)." + } + ], + "data_format": "MITRE", + "data_type": "CVE", + "data_version": "4.0", + "description": { + "description_data": [ + { + "lang": "eng", + "value": "Multiple Authenticated (admin user role) Persistent Cross-Site Scripting (XSS) vulnerabilities discovered in AMP for WP – Accelerated Mobile Pages WordPress plugin (versions <= 1.0.77.32)." + } + ] + }, + "generator": { + "engine": "Vulnogram 0.0.9" + }, + "impact": { + "cvss": { + "attackComplexity": "LOW", + "attackVector": "NETWORK", + "availabilityImpact": "NONE", + "baseScore": 4.8, + "baseSeverity": "MEDIUM", + "confidentialityImpact": "LOW", + "integrityImpact": "LOW", + "privilegesRequired": "HIGH", + "scope": "CHANGED", + "userInteraction": "REQUIRED", + "vectorString": "CVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:C/C:L/I:L/A:N", + "version": "3.1" + } + }, + "problemtype": { + "problemtype_data": [ + { + "description": [ + { + "lang": "eng", + "value": "CWE-79 Cross-site Scripting (XSS)" + } + ] + } + ] + }, + "references": { + "reference_data": [ + { + "name": "https://wordpress.org/plugins/accelerated-mobile-pages/#developers", + "refsource": "CONFIRM", + "url": "https://wordpress.org/plugins/accelerated-mobile-pages/#developers" + }, + { + "name": "https://patchstack.com/database/vulnerability/accelerated-mobile-pages/wordpress-amp-for-wp-accelerated-mobile-pages-plugin-1-0-77-32-multiple-authenticated-persistent-cross-site-scripting-xss-vulnerabilities", + "refsource": "CONFIRM", + "url": "https://patchstack.com/database/vulnerability/accelerated-mobile-pages/wordpress-amp-for-wp-accelerated-mobile-pages-plugin-1-0-77-32-multiple-authenticated-persistent-cross-site-scripting-xss-vulnerabilities" + } + ] + }, + "solution": [ + { + "lang": "en", + "value": "Update to 1.0.77.33 or higher version." + } + ], + "source": { + "discovery": "EXTERNAL" + } + } + }, + "adp": [ + { + "providerMetadata": { + "orgId": "af854a3a-2127-422b-91ae-364da2661108", + "shortName": "CVE", + "dateUpdated": "2024-08-03T19:05:55.659Z" + }, + "title": "CVE Program Container", + "references": [ + { + "tags": [ + "vdb-entry", + "x_transferred" + ], + "url": "https://patchstack.com/database/vulnerability/accelerated-mobile-pages/wordpress-amp-for-wp-accelerated-mobile-pages-plugin-1-0-77-32-multiple-authenticated-persistent-cross-site-scripting-xss-vulnerabilities?_s_id=cve" + } + ] + }, + { + "metrics": [ + { + "other": { + "type": "ssvc", + "content": { + "timestamp": "2025-04-23T13:06:51.972194Z", + "id": "CVE-2021-23209", + "options": [ + { + "Exploitation": "none" + }, + { + "Automatable": "no" + }, + { + "Technical Impact": "partial" + } + ], + "role": "CISA Coordinator", + "version": "2.0.3" + } + } + } + ], + "title": "CISA ADP Vulnrichment", + "providerMetadata": { + "orgId": "134c704f-9b21-4f2e-91b3-4a467353bcc0", + "shortName": "CISA-ADP", + "dateUpdated": "2025-04-23T18:45:39.935Z" + } + } + ] + }, + "cveMetadata": { + "assignerOrgId": "21595511-bba5-4825-b968-b78d1f9984a3", + "assignerShortName": "Patchstack", + "cveId": "CVE-2021-23209", + "datePublished": "2022-03-18T18:00:25.146Z", + "dateReserved": "2022-01-13T00:00:00.000Z", + "dateUpdated": "2026-04-28T16:07:30.318Z", + "state": "PUBLISHED" + }, + "dataType": "CVE_RECORD", + "dataVersion": "5.2" +} \ No newline at end of file diff --git a/vulnfeeds/test_data/cvelistV5/cves/2024/27xxx/CVE-2024-27098.json b/vulnfeeds/test_data/cvelistV5/cves/2024/27xxx/CVE-2024-27098.json new file mode 100644 index 00000000000..1426239e54f --- /dev/null +++ b/vulnfeeds/test_data/cvelistV5/cves/2024/27xxx/CVE-2024-27098.json @@ -0,0 +1,166 @@ +{ + "dataType": "CVE_RECORD", + "dataVersion": "5.1", + "cveMetadata": { + "cveId": "CVE-2024-27098", + "assignerOrgId": "a0819718-46f1-4df5-94e2-005712e83aaa", + "state": "PUBLISHED", + "assignerShortName": "GitHub_M", + "dateReserved": "2024-02-19T14:43:05.993Z", + "datePublished": "2024-03-18T16:14:18.894Z", + "dateUpdated": "2024-08-02T00:27:59.073Z" + }, + "containers": { + "cna": { + "title": "Blind Server-Side Request Forgery (SSRF) using Arbitrary Object Instantiation in GLPI", + "problemTypes": [ + { + "descriptions": [ + { + "cweId": "CWE-918", + "lang": "en", + "description": "CWE-918: Server-Side Request Forgery (SSRF)", + "type": "CWE" + } + ] + } + ], + "metrics": [ + { + "cvssV3_1": { + "attackComplexity": "LOW", + "attackVector": "NETWORK", + "availabilityImpact": "NONE", + "baseScore": 6.4, + "baseSeverity": "MEDIUM", + "confidentialityImpact": "LOW", + "integrityImpact": "LOW", + "privilegesRequired": "LOW", + "scope": "CHANGED", + "userInteraction": "NONE", + "vectorString": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:L/A:N", + "version": "3.1" + } + } + ], + "references": [ + { + "name": "https://github.com/glpi-project/glpi/security/advisories/GHSA-92x4-q9w5-837w", + "tags": [ + "x_refsource_CONFIRM" + ], + "url": "https://github.com/glpi-project/glpi/security/advisories/GHSA-92x4-q9w5-837w" + }, + { + "name": "https://github.com/glpi-project/glpi/commit/3b6bc1b4aa1f3693b20ada3425d2de5108522484", + "tags": [ + "x_refsource_MISC" + ], + "url": "https://github.com/glpi-project/glpi/commit/3b6bc1b4aa1f3693b20ada3425d2de5108522484" + }, + { + "name": "https://github.com/glpi-project/glpi/releases/tag/10.0.13", + "tags": [ + "x_refsource_MISC" + ], + "url": "https://github.com/glpi-project/glpi/releases/tag/10.0.13" + } + ], + "affected": [ + { + "vendor": "glpi-project", + "product": "glpi", + "versions": [ + { + "version": ">= 9.5.0, < 10.0.13", + "status": "affected" + } + ] + } + ], + "providerMetadata": { + "orgId": "a0819718-46f1-4df5-94e2-005712e83aaa", + "shortName": "GitHub_M", + "dateUpdated": "2024-03-18T16:14:18.894Z" + }, + "descriptions": [ + { + "lang": "en", + "value": "GLPI is a Free Asset and IT Management Software package, Data center management, ITIL Service Desk, licenses tracking and software auditing. An authenticated user can execute a SSRF based attack using Arbitrary Object Instantiation. This issue has been patched in version 10.0.13." + } + ], + "source": { + "advisory": "GHSA-92x4-q9w5-837w", + "discovery": "UNKNOWN" + } + }, + "adp": [ + { + "title": "CISA ADP Vulnrichment", + "metrics": [ + { + "other": { + "type": "ssvc", + "content": { + "id": "CVE-2024-27098", + "role": "CISA Coordinator", + "options": [ + { + "Exploitation": "none" + }, + { + "Automatable": "no" + }, + { + "Technical Impact": "partial" + } + ], + "version": "2.0.3", + "timestamp": "2024-03-19T15:47:43.513847Z" + } + } + } + ], + "providerMetadata": { + "orgId": "134c704f-9b21-4f2e-91b3-4a467353bcc0", + "shortName": "CISA-ADP", + "dateUpdated": "2024-06-04T17:47:14.574Z" + } + }, + { + "providerMetadata": { + "orgId": "af854a3a-2127-422b-91ae-364da2661108", + "shortName": "CVE", + "dateUpdated": "2024-08-02T00:27:59.073Z" + }, + "title": "CVE Program Container", + "references": [ + { + "name": "https://github.com/glpi-project/glpi/security/advisories/GHSA-92x4-q9w5-837w", + "tags": [ + "x_refsource_CONFIRM", + "x_transferred" + ], + "url": "https://github.com/glpi-project/glpi/security/advisories/GHSA-92x4-q9w5-837w" + }, + { + "name": "https://github.com/glpi-project/glpi/commit/3b6bc1b4aa1f3693b20ada3425d2de5108522484", + "tags": [ + "x_refsource_MISC", + "x_transferred" + ], + "url": "https://github.com/glpi-project/glpi/commit/3b6bc1b4aa1f3693b20ada3425d2de5108522484" + }, + { + "name": "https://github.com/glpi-project/glpi/releases/tag/10.0.13", + "tags": [ + "x_refsource_MISC", + "x_transferred" + ], + "url": "https://github.com/glpi-project/glpi/releases/tag/10.0.13" + } + ] + } + ] + } +} \ No newline at end of file diff --git a/vulnfeeds/test_data/cvelistV5/cves/2026/1xxx/CVE-2026-1293.json b/vulnfeeds/test_data/cvelistV5/cves/2026/1xxx/CVE-2026-1293.json new file mode 100644 index 00000000000..31acf3a7fdf --- /dev/null +++ b/vulnfeeds/test_data/cvelistV5/cves/2026/1xxx/CVE-2026-1293.json @@ -0,0 +1,133 @@ +{ + "dataType": "CVE_RECORD", + "dataVersion": "5.2", + "cveMetadata": { + "cveId": "CVE-2026-1293", + "assignerOrgId": "b15e7b5b-3da4-40ae-a43c-f7aa60e62599", + "state": "PUBLISHED", + "assignerShortName": "Wordfence", + "dateReserved": "2026-01-21T16:53:09.134Z", + "datePublished": "2026-02-06T11:21:30.973Z", + "dateUpdated": "2026-04-08T17:05:48.147Z" + }, + "containers": { + "cna": { + "providerMetadata": { + "orgId": "b15e7b5b-3da4-40ae-a43c-f7aa60e62599", + "shortName": "Wordfence", + "dateUpdated": "2026-04-08T17:05:48.147Z" + }, + "affected": [ + { + "vendor": "yoast", + "product": "Yoast SEO – Advanced SEO with real-time guidance and built-in AI", + "versions": [ + { + "version": "0", + "status": "affected", + "lessThanOrEqual": "26.8", + "versionType": "semver" + } + ], + "defaultStatus": "unaffected" + } + ], + "descriptions": [ + { + "lang": "en", + "value": "The Yoast SEO – Advanced SEO with real-time guidance and built-in AI plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the the `yoast-schema` block attribute in all versions up to, and including, 26.8 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with Contributor-level access and above, to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page." + } + ], + "title": "Yoast SEO <= 26.8 - Authenticated (Contributor+) Stored Cross-Site Scripting via 'yoast-schema' Block Attribute", + "references": [ + { + "url": "https://www.wordfence.com/threat-intel/vulnerabilities/id/8b2e7c2d-ed2f-439b-9cee-f2e5d46121b6?source=cve" + }, + { + "url": "https://plugins.trac.wordpress.org/browser/wordpress-seo/tags/26.8/src/presenters/schema-presenter.php#L49" + }, + { + "url": "https://plugins.trac.wordpress.org/browser/wordpress-seo/tags/26.8/inc/class-wpseo-utils.php#L915" + }, + { + "url": "https://plugins.trac.wordpress.org/browser/wordpress-seo/tags/26.8/src/generators/schema-generator.php#L188" + } + ], + "problemTypes": [ + { + "descriptions": [ + { + "lang": "en", + "description": "CWE-79 Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')", + "cweId": "CWE-79", + "type": "CWE" + } + ] + } + ], + "metrics": [ + { + "cvssV3_1": { + "version": "3.1", + "vectorString": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:L/A:N", + "baseScore": 6.4, + "baseSeverity": "MEDIUM" + } + } + ], + "credits": [ + { + "lang": "en", + "type": "finder", + "value": "suyoung kim" + } + ], + "timeline": [ + { + "time": "2026-01-09T00:00:00.000Z", + "lang": "en", + "value": "Discovered" + }, + { + "time": "2026-02-05T22:18:00.000Z", + "lang": "en", + "value": "Disclosed" + } + ] + }, + "adp": [ + { + "metrics": [ + { + "other": { + "type": "ssvc", + "content": { + "timestamp": "2026-02-06T12:27:02.594220Z", + "id": "CVE-2026-1293", + "options": [ + { + "Exploitation": "none" + }, + { + "Automatable": "no" + }, + { + "Technical Impact": "partial" + } + ], + "role": "CISA Coordinator", + "version": "2.0.3" + } + } + } + ], + "title": "CISA ADP Vulnrichment", + "providerMetadata": { + "orgId": "134c704f-9b21-4f2e-91b3-4a467353bcc0", + "shortName": "CISA-ADP", + "dateUpdated": "2026-02-06T12:27:32.895Z" + } + } + ] + } +} \ No newline at end of file