Skip to content

Commit

Permalink
feat: disable cpe vendor wildcards to reduce false positives (#1647)
Browse files Browse the repository at this point in the history
* improved parsing of vendor from github url

Signed-off-by: Weston Steimel <weston.steimel@anchore.com>

* stop generating wildcard vendors

Add logic for parsing javascript and ruby package vendor candidates from
url and author fields and stop generating wildcard vendor candidates

Signed-off-by: Weston Steimel <weston.steimel@anchore.com>

---------

Signed-off-by: Weston Steimel <weston.steimel@anchore.com>
  • Loading branch information
westonsteimel authored Mar 3, 2023
1 parent 01230aa commit c4cbe21
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 16 deletions.
14 changes: 7 additions & 7 deletions syft/pkg/cataloger/common/cpe/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,6 @@ func candidateVendors(p pkg.Package) []string {
}
}

// some ecosystems do not have enough metadata to determine the vendor accurately, in which case we selectively
// allow * as a candidate. Note: do NOT allow Java packages to have * vendors.
switch p.Language {
case pkg.Ruby, pkg.JavaScript:
vendors.addValue(wfn.Any)
}

switch p.MetadataType {
case pkg.RpmMetadataType:
vendors.union(candidateVendorsForRPM(p))
Expand All @@ -111,8 +104,15 @@ func candidateVendors(p pkg.Package) []string {
vendors.union(candidateVendorsForJava(p))
case pkg.ApkMetadataType:
vendors.union(candidateVendorsForAPK(p))
case pkg.NpmPackageJSONMetadataType:
vendors.union(candidateVendorsForJavascript(p))
}

// We should no longer be generating vendor candidates with these values ["" and "*"]
// (since CPEs will match any other value)
vendors.removeByValue("")
vendors.removeByValue("*")

// try swapping hyphens for underscores, vice versa, and removing separators altogether
addDelimiterVariations(vendors)

Expand Down
21 changes: 13 additions & 8 deletions syft/pkg/cataloger/common/cpe/generate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,15 +117,20 @@ func TestGeneratePackageCPEs(t *testing.T) {
{
name: "javascript language",
p: pkg.Package{
Name: "name",
Version: "3.2",
FoundBy: "some-analyzer",
Language: pkg.JavaScript,
Type: pkg.DebPkg,
Name: "name",
Version: "3.2",
FoundBy: "some-analyzer",
Language: pkg.JavaScript,
MetadataType: pkg.NpmPackageJSONMetadataType,
Metadata: pkg.NpmPackageJSONMetadata{
Author: "jon",
URL: "https://github.com/bob/npm-name",
},
},
expected: []string{
"cpe:2.3:a:name:name:3.2:*:*:*:*:*:*:*",
"cpe:2.3:a:*:name:3.2:*:*:*:*:*:*:*",
"cpe:2.3:a:jon:name:3.2:*:*:*:*:*:*:*",
"cpe:2.3:a:bob:name:3.2:*:*:*:*:*:*:*",
},
},
{
Expand All @@ -142,10 +147,10 @@ func TestGeneratePackageCPEs(t *testing.T) {
"someones name",
"someones.elses.name@gmail.com",
},
Homepage: "https://github.com/tom/ruby-name",
},
},
expected: []string{
"cpe:2.3:a:*:name:3.2:*:*:*:*:*:*:*",
"cpe:2.3:a:name:name:3.2:*:*:*:*:*:*:*",
"cpe:2.3:a:ruby-lang:name:3.2:*:*:*:*:*:*:*",
"cpe:2.3:a:ruby:name:3.2:*:*:*:*:*:*:*",
Expand All @@ -154,6 +159,7 @@ func TestGeneratePackageCPEs(t *testing.T) {
"cpe:2.3:a:someones-name:name:3.2:*:*:*:*:*:*:*",
"cpe:2.3:a:someones_elses_name:name:3.2:*:*:*:*:*:*:*",
"cpe:2.3:a:someones_name:name:3.2:*:*:*:*:*:*:*",
"cpe:2.3:a:tom:name:3.2:*:*:*:*:*:*:*",
},
},
{
Expand Down Expand Up @@ -641,7 +647,6 @@ func TestGeneratePackageCPEs(t *testing.T) {
},
},
expected: []string{
"cpe:2.3:a:*:bundler:2.1.4:*:*:*:*:*:*:*",
"cpe:2.3:a:bundler:bundler:2.1.4:*:*:*:*:*:*:*",
"cpe:2.3:a:ruby-lang:bundler:2.1.4:*:*:*:*:*:*:*",
"cpe:2.3:a:ruby:bundler:2.1.4:*:*:*:*:*:*:*",
Expand Down
32 changes: 32 additions & 0 deletions syft/pkg/cataloger/common/cpe/javascript.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package cpe

import "github.com/anchore/syft/syft/pkg"

func candidateVendorsForJavascript(p pkg.Package) fieldCandidateSet {
if p.MetadataType != pkg.NpmPackageJSONMetadataType {
return nil
}

vendors := newFieldCandidateSet()
metadata, ok := p.Metadata.(pkg.NpmPackageJSONMetadata)
if !ok {
return nil
}

if metadata.Author != "" {
vendors.add(fieldCandidate{
value: normalizePersonName(stripEmailSuffix(metadata.Author)),
disallowSubSelections: true,
})
}

if metadata.URL != "" {
vendors.union(candidateVendorsFromURL(metadata.URL))
}

if metadata.Homepage != "" {
vendors.union(candidateVendorsFromURL(metadata.Homepage))
}

return vendors
}
5 changes: 5 additions & 0 deletions syft/pkg/cataloger/common/cpe/ruby.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,10 @@ func candidateVendorsForRuby(p pkg.Package) fieldCandidateSet {
disallowSubSelections: true,
})
}

if metadata.Homepage != "" {
vendors.union(candidateVendorsFromURL(metadata.Homepage))
}

return vendors
}
2 changes: 1 addition & 1 deletion syft/pkg/cataloger/common/cpe/vendors_from_url.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ var (
}

vendorExtractionPatterns = []*regexp.Regexp{
regexp.MustCompile(`^https://(?:github|gitlab)\.com/(?P<vendor>[\w\-]*?)/.*$`),
regexp.MustCompile(`^(?:https|http|git)://(?:github|gitlab)\.com/(?P<vendor>[\w\-]*?)/.*$`),
}
)

Expand Down
10 changes: 10 additions & 0 deletions syft/pkg/cataloger/common/cpe/vendors_from_url_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,16 @@ func Test_candidateVendorsFromURL(t *testing.T) {
url: "https://github.com/armadillo/abcxyz-12345/a/b/c/d/e/f/g",
expected: []string{"armadillo"},
},
{
name: "github username from git://",
url: "git://github.com/abc/xyz.git",
expected: []string{"abc"},
},
{
name: "github username from http://",
url: "http://github.com/abc/xyz.git",
expected: []string{"abc"},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
Expand Down

0 comments on commit c4cbe21

Please sign in to comment.