mirror of
https://github.com/anchore/syft.git
synced 2026-11-04 16:36:40 +01:00
feat: Record where CPEs come from (#2552)
Syft can get CPEs from several source, including generating them based on package data, finding them in the NVD CPE dictionary, or finding them declared in a manifest or existing SBOM. Record where Syft got CPEs so that consumers of SBOMs can reason about how trustworthy they are. Signed-off-by: Will Murphy <will.murphy@anchore.com>
This commit is contained in:
@@ -1282,7 +1282,7 @@ func TestCatalogerConfig_MarshalJSON(t *testing.T) {
|
||||
Qualifiers: nil,
|
||||
Subpath: "subpath",
|
||||
},
|
||||
CPEs: []cpe.CPE{cpe.Must("cpe:2.3:a:some:app:*:*:*:*:*:*:*:*")},
|
||||
CPEs: []cpe.CPE{cpe.Must("cpe:2.3:a:some:app:*:*:*:*:*:*:*:*", cpe.GeneratedSource)},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -56,7 +56,7 @@ func (cfg Classifier) MarshalJSON() ([]byte, error) {
|
||||
|
||||
var marshalledCPEs []string
|
||||
for _, c := range cfg.CPEs {
|
||||
marshalledCPEs = append(marshalledCPEs, c.BindToFmtString())
|
||||
marshalledCPEs = append(marshalledCPEs, c.Attributes.BindToFmtString())
|
||||
}
|
||||
|
||||
m := marshalled{
|
||||
@@ -225,10 +225,11 @@ func getContents(resolver file.Resolver, location file.Location) ([]byte, error)
|
||||
return contents, nil
|
||||
}
|
||||
|
||||
// singleCPE returns a []pkg.CPE based on the cpe string or panics if the CPE is invalid
|
||||
// singleCPE returns a []cpe.CPE with Source: Generated based on the cpe string or panics if the
|
||||
// cpe string cannot be parsed into valid CPE Attributes
|
||||
func singleCPE(cpeString string) []cpe.CPE {
|
||||
return []cpe.CPE{
|
||||
cpe.Must(cpeString),
|
||||
cpe.Must(cpeString, cpe.GeneratedSource),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,14 +30,14 @@ func Test_ClassifierCPEs(t *testing.T) {
|
||||
cpes: nil,
|
||||
},
|
||||
{
|
||||
name: "one CPE",
|
||||
name: "one Attributes",
|
||||
fixture: "test-fixtures/version.txt",
|
||||
classifier: Classifier{
|
||||
Package: "some-app",
|
||||
FileGlob: "**/version.txt",
|
||||
EvidenceMatcher: FileContentsVersionMatcher(`(?m)my-verison:(?P<version>[0-9.]+)`),
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:a:some:app:*:*:*:*:*:*:*:*"),
|
||||
cpe.Must("cpe:2.3:a:some:app:*:*:*:*:*:*:*:*", cpe.GeneratedSource),
|
||||
},
|
||||
},
|
||||
cpes: []string{
|
||||
@@ -52,8 +52,8 @@ func Test_ClassifierCPEs(t *testing.T) {
|
||||
FileGlob: "**/version.txt",
|
||||
EvidenceMatcher: FileContentsVersionMatcher(`(?m)my-verison:(?P<version>[0-9.]+)`),
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:a:some:app:*:*:*:*:*:*:*:*"),
|
||||
cpe.Must("cpe:2.3:a:some:apps:*:*:*:*:*:*:*:*"),
|
||||
cpe.Must("cpe:2.3:a:some:app:*:*:*:*:*:*:*:*", cpe.GeneratedSource),
|
||||
cpe.Must("cpe:2.3:a:some:apps:*:*:*:*:*:*:*:*", cpe.GeneratedSource),
|
||||
},
|
||||
},
|
||||
cpes: []string{
|
||||
@@ -79,7 +79,7 @@ func Test_ClassifierCPEs(t *testing.T) {
|
||||
|
||||
var cpes []string
|
||||
for _, c := range p.CPEs {
|
||||
cpes = append(cpes, c.String())
|
||||
cpes = append(cpes, c.Attributes.String())
|
||||
}
|
||||
require.Equal(t, test.cpes, cpes)
|
||||
})
|
||||
@@ -109,7 +109,7 @@ func TestClassifier_MarshalJSON(t *testing.T) {
|
||||
Qualifiers: nil,
|
||||
Subpath: "subpath",
|
||||
},
|
||||
CPEs: []cpe.CPE{cpe.Must("cpe:2.3:a:some:app:*:*:*:*:*:*:*:*")},
|
||||
CPEs: []cpe.CPE{cpe.Must("cpe:2.3:a:some:app:*:*:*:*:*:*:*:*", cpe.GeneratedSource)},
|
||||
},
|
||||
want: `{"class":"class","fileGlob":"glob","package":"pkg","purl":"pkg:type/namespace/name@version#subpath","cpes":["cpe:2.3:a:some:app:*:*:*:*:*:*:*:*"]}`,
|
||||
},
|
||||
|
||||
@@ -23,8 +23,8 @@ func DefaultClassifiers() []Classifier {
|
||||
Package: "python",
|
||||
PURL: mustPURL("pkg:generic/python@version"),
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:a:python_software_foundation:python:*:*:*:*:*:*:*:*"),
|
||||
cpe.Must("cpe:2.3:a:python:python:*:*:*:*:*:*:*:*"),
|
||||
cpe.Must("cpe:2.3:a:python_software_foundation:python:*:*:*:*:*:*:*:*", cpe.GeneratedSource),
|
||||
cpe.Must("cpe:2.3:a:python:python:*:*:*:*:*:*:*:*", cpe.GeneratedSource),
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -34,8 +34,8 @@ func DefaultClassifiers() []Classifier {
|
||||
Package: "python",
|
||||
PURL: mustPURL("pkg:generic/python@version"),
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:a:python_software_foundation:python:*:*:*:*:*:*:*:*"),
|
||||
cpe.Must("cpe:2.3:a:python:python:*:*:*:*:*:*:*:*"),
|
||||
cpe.Must("cpe:2.3:a:python_software_foundation:python:*:*:*:*:*:*:*:*", cpe.GeneratedSource),
|
||||
cpe.Must("cpe:2.3:a:python:python:*:*:*:*:*:*:*:*", cpe.GeneratedSource),
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -93,7 +93,7 @@ func DefaultClassifiers() []Classifier {
|
||||
`(?m)\x00openjdk\x00java\x00(?P<release>[0-9]+[.0-9]*)\x00(?P<version>[0-9]+[^\x00]+)\x00`),
|
||||
Package: "java",
|
||||
PURL: mustPURL("pkg:generic/java@version"),
|
||||
// TODO the updates might need to be part of the CPE, like: 1.8.0:update152
|
||||
// TODO the updates might need to be part of the CPE Attributes, like: 1.8.0:update152
|
||||
CPEs: singleCPE("cpe:2.3:a:oracle:openjdk:*:*:*:*:*:*:*:*"),
|
||||
},
|
||||
{
|
||||
@@ -255,8 +255,8 @@ func DefaultClassifiers() []Classifier {
|
||||
Package: "percona-server",
|
||||
PURL: mustPURL("pkg:generic/percona-server@version"),
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:a:oracle:mysql:*:*:*:*:*:*:*:*"),
|
||||
cpe.Must("cpe:2.3:a:percona:percona_server:*:*:*:*:*:*:*:*"),
|
||||
cpe.Must("cpe:2.3:a:oracle:mysql:*:*:*:*:*:*:*:*", cpe.GeneratedSource),
|
||||
cpe.Must("cpe:2.3:a:percona:percona_server:*:*:*:*:*:*:*:*", cpe.GeneratedSource),
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -267,9 +267,9 @@ func DefaultClassifiers() []Classifier {
|
||||
Package: "percona-xtradb-cluster",
|
||||
PURL: mustPURL("pkg:generic/percona-xtradb-cluster@version"),
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:a:oracle:mysql:*:*:*:*:*:*:*:*"),
|
||||
cpe.Must("cpe:2.3:a:percona:percona_server:*:*:*:*:*:*:*:*"),
|
||||
cpe.Must("cpe:2.3:a:percona:xtradb_cluster:*:*:*:*:*:*:*:*"),
|
||||
cpe.Must("cpe:2.3:a:oracle:mysql:*:*:*:*:*:*:*:*", cpe.GeneratedSource),
|
||||
cpe.Must("cpe:2.3:a:percona:percona_server:*:*:*:*:*:*:*:*", cpe.GeneratedSource),
|
||||
cpe.Must("cpe:2.3:a:percona:xtradb_cluster:*:*:*:*:*:*:*:*", cpe.GeneratedSource),
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -363,8 +363,8 @@ func DefaultClassifiers() []Classifier {
|
||||
Package: "nginx",
|
||||
PURL: mustPURL("pkg:generic/nginx@version"),
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:a:f5:nginx:*:*:*:*:*:*:*:*"),
|
||||
cpe.Must("cpe:2.3:a:nginx:nginx:*:*:*:*:*:*:*:*"),
|
||||
cpe.Must("cpe:2.3:a:f5:nginx:*:*:*:*:*:*:*:*", cpe.GeneratedSource),
|
||||
cpe.Must("cpe:2.3:a:nginx:nginx:*:*:*:*:*:*:*:*", cpe.GeneratedSource),
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -21,8 +21,8 @@ func newPackage(classifier Classifier, location file.Location, matchMetadata map
|
||||
|
||||
var cpes []cpe.CPE
|
||||
for _, c := range classifier.CPEs {
|
||||
c.Version = version
|
||||
c.Update = update
|
||||
c.Attributes.Version = version
|
||||
c.Attributes.Update = update
|
||||
cpes = append(cpes, c)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user