mirror of
https://github.com/anchore/syft.git
synced 2025-11-17 16:33:21 +01:00
Consider Author field for wordpress plugins when generating CPEs (#2946)
* enhance wordpress vendor candidates for CPEs Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * encode wordpress plugin target software Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> --------- Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
This commit is contained in:
parent
f966bcfd03
commit
0956753409
@ -129,23 +129,26 @@ func FromDictionaryFind(p pkg.Package) ([]cpe.CPE, bool) {
|
|||||||
func FromPackageAttributes(p pkg.Package) []cpe.CPE {
|
func FromPackageAttributes(p pkg.Package) []cpe.CPE {
|
||||||
vendors := candidateVendors(p)
|
vendors := candidateVendors(p)
|
||||||
products := candidateProducts(p)
|
products := candidateProducts(p)
|
||||||
|
targetSWs := candidateTargetSw(p)
|
||||||
if len(products) == 0 {
|
if len(products) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
keys := strset.New()
|
keys := strset.New()
|
||||||
cpes := make([]cpe.Attributes, 0)
|
cpes := make([]cpe.Attributes, 0)
|
||||||
for _, product := range products {
|
for _, ts := range targetSWs {
|
||||||
for _, vendor := range vendors {
|
for _, product := range products {
|
||||||
// prevent duplicate entries...
|
for _, vendor := range vendors {
|
||||||
key := fmt.Sprintf("%s|%s|%s", product, vendor, p.Version)
|
// prevent duplicate entries...
|
||||||
if keys.Has(key) {
|
key := fmt.Sprintf("%s|%s|%s|%s", product, vendor, p.Version, ts)
|
||||||
continue
|
if keys.Has(key) {
|
||||||
}
|
continue
|
||||||
keys.Add(key)
|
}
|
||||||
// add a new entry...
|
keys.Add(key)
|
||||||
if c := newCPE(product, vendor, p.Version, cpe.Any); c != nil {
|
// add a new entry...
|
||||||
cpes = append(cpes, *c)
|
if c := newCPE(product, vendor, p.Version, ts); c != nil {
|
||||||
|
cpes = append(cpes, *c)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -162,6 +165,13 @@ func FromPackageAttributes(p pkg.Package) []cpe.CPE {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func candidateTargetSw(p pkg.Package) []string {
|
||||||
|
if p.Type == pkg.WordpressPluginPkg {
|
||||||
|
return []string{"wordpress"}
|
||||||
|
}
|
||||||
|
return []string{cpe.Any}
|
||||||
|
}
|
||||||
|
|
||||||
//nolint:funlen
|
//nolint:funlen
|
||||||
func candidateVendors(p pkg.Package) []string {
|
func candidateVendors(p pkg.Package) []string {
|
||||||
// in ecosystems where the packaging metadata does not have a clear field to indicate a vendor (or a field that
|
// in ecosystems where the packaging metadata does not have a clear field to indicate a vendor (or a field that
|
||||||
|
|||||||
@ -719,6 +719,31 @@ func TestGeneratePackageCPEs(t *testing.T) {
|
|||||||
"cpe:2.3:a:ruby_rake:ruby_rake:2.7.6-r0:*:*:*:*:*:*:*",
|
"cpe:2.3:a:ruby_rake:ruby_rake:2.7.6-r0:*:*:*:*:*:*:*",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "wordpress plugin",
|
||||||
|
p: pkg.Package{
|
||||||
|
Name: "WP Coder",
|
||||||
|
Version: "2.5.1",
|
||||||
|
Type: pkg.WordpressPluginPkg,
|
||||||
|
Metadata: pkg.WordpressPluginEntry{
|
||||||
|
PluginInstallDirectory: "wp-coder",
|
||||||
|
Author: "Wow-Company",
|
||||||
|
AuthorURI: "https://wow-estore.com",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: []string{
|
||||||
|
"cpe:2.3:a:wow-company:wp-coder:2.5.1:*:*:*:*:wordpress:*:*",
|
||||||
|
"cpe:2.3:a:wow-company:wp_coder:2.5.1:*:*:*:*:wordpress:*:*", // this is the correct CPE relative to CVE-2021-25053
|
||||||
|
"cpe:2.3:a:wow-estore:wp-coder:2.5.1:*:*:*:*:wordpress:*:*",
|
||||||
|
"cpe:2.3:a:wow-estore:wp_coder:2.5.1:*:*:*:*:wordpress:*:*",
|
||||||
|
"cpe:2.3:a:wow:wp-coder:2.5.1:*:*:*:*:wordpress:*:*",
|
||||||
|
"cpe:2.3:a:wow:wp_coder:2.5.1:*:*:*:*:wordpress:*:*",
|
||||||
|
"cpe:2.3:a:wow_company:wp-coder:2.5.1:*:*:*:*:wordpress:*:*",
|
||||||
|
"cpe:2.3:a:wow_company:wp_coder:2.5.1:*:*:*:*:wordpress:*:*",
|
||||||
|
"cpe:2.3:a:wow_estore:wp-coder:2.5.1:*:*:*:*:wordpress:*:*",
|
||||||
|
"cpe:2.3:a:wow_estore:wp_coder:2.5.1:*:*:*:*:wordpress:*:*",
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
|
|||||||
@ -21,12 +21,18 @@ func candidateVendorsForWordpressPlugin(p pkg.Package) fieldCandidateSet {
|
|||||||
|
|
||||||
vendors := newFieldCandidateSet()
|
vendors := newFieldCandidateSet()
|
||||||
|
|
||||||
|
if metadata.Author != "" {
|
||||||
|
vendors.addValue(strings.ToLower(metadata.Author))
|
||||||
|
}
|
||||||
|
|
||||||
if metadata.AuthorURI != "" {
|
if metadata.AuthorURI != "" {
|
||||||
matchMap := internal.MatchNamedCaptureGroups(vendorFromURLRegexp, metadata.AuthorURI)
|
matchMap := internal.MatchNamedCaptureGroups(vendorFromURLRegexp, metadata.AuthorURI)
|
||||||
if vendor, ok := matchMap["vendor"]; ok && vendor != "" {
|
if vendor, ok := matchMap["vendor"]; ok && vendor != "" {
|
||||||
vendors.addValue(vendor)
|
vendors.addValue(strings.ToLower(vendor))
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
if len(vendors) == 0 {
|
||||||
// add plugin_name + _project as a vendor if no Author URI found
|
// add plugin_name + _project as a vendor if no Author URI found
|
||||||
vendors.addValue(fmt.Sprintf("%s_project", normalizeWordpressPluginName(p.Name)))
|
vendors.addValue(fmt.Sprintf("%s_project", normalizeWordpressPluginName(p.Name)))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,7 +24,7 @@ func Test_candidateVendorsForWordpressPlugin(t *testing.T) {
|
|||||||
AuthorURI: "https://automattic.com/wordpress-plugins/",
|
AuthorURI: "https://automattic.com/wordpress-plugins/",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expected: []string{"automattic"},
|
expected: []string{"automattic - anti-spam team", "automattic"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "All-in-One WP Migration",
|
name: "All-in-One WP Migration",
|
||||||
@ -47,7 +47,7 @@ func Test_candidateVendorsForWordpressPlugin(t *testing.T) {
|
|||||||
AuthorURI: "https://bookingultrapro.com/",
|
AuthorURI: "https://bookingultrapro.com/",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expected: []string{"bookingultrapro"},
|
expected: []string{"booking ultra pro", "bookingultrapro"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Coming Soon Chop Chop",
|
name: "Coming Soon Chop Chop",
|
||||||
@ -58,7 +58,7 @@ func Test_candidateVendorsForWordpressPlugin(t *testing.T) {
|
|||||||
AuthorURI: "https://www.chop-chop.org",
|
AuthorURI: "https://www.chop-chop.org",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expected: []string{"chop-chop"},
|
expected: []string{"chop-chop.org", "chop-chop"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Access Code Feeder",
|
name: "Access Code Feeder",
|
||||||
@ -71,6 +71,22 @@ func Test_candidateVendorsForWordpressPlugin(t *testing.T) {
|
|||||||
// When a plugin as no `Author URI` use plugin_name + _project as a vendor
|
// When a plugin as no `Author URI` use plugin_name + _project as a vendor
|
||||||
expected: []string{"access_code_feeder_project"},
|
expected: []string{"access_code_feeder_project"},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "WP Coder",
|
||||||
|
pkg: pkg.Package{
|
||||||
|
Name: "WP Coder",
|
||||||
|
Metadata: pkg.WordpressPluginEntry{
|
||||||
|
PluginInstallDirectory: "wp-coder",
|
||||||
|
Author: "Wow-Company",
|
||||||
|
AuthorURI: "https://wow-estore.com/",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// found in the wild https://plugins.trac.wordpress.org/browser/wp-coder/tags/2.5.1/wp-coder.php
|
||||||
|
expected: []string{
|
||||||
|
"wow-company", // this is the correct answer relative to CPEs registered on CVE-2021-25053
|
||||||
|
"wow-estore",
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user