mirror of
https://github.com/anchore/syft.git
synced 2026-11-01 15:06:36 +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:
@@ -159,11 +159,14 @@ func Test_encodeDecodeFileMetadata(t *testing.T) {
|
||||
Type: "type",
|
||||
CPEs: []cpe.CPE{
|
||||
{
|
||||
Part: "a",
|
||||
Vendor: "vendor",
|
||||
Product: "product",
|
||||
Version: "version",
|
||||
Update: "update",
|
||||
Attributes: cpe.Attributes{
|
||||
Part: "a",
|
||||
Vendor: "vendor",
|
||||
Product: "product",
|
||||
Version: "version",
|
||||
Update: "update",
|
||||
},
|
||||
Source: "test-source",
|
||||
},
|
||||
},
|
||||
PURL: "pkg:generic/pkg@version",
|
||||
|
||||
@@ -152,7 +152,7 @@ func TestEncodeFullJSONDocument(t *testing.T) {
|
||||
},
|
||||
PURL: "a-purl-1",
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:*:some:package:1:*:*:*:*:*:*:*"),
|
||||
cpe.Must("cpe:2.3:*:some:package:1:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource),
|
||||
},
|
||||
}
|
||||
|
||||
@@ -173,7 +173,7 @@ func TestEncodeFullJSONDocument(t *testing.T) {
|
||||
},
|
||||
PURL: "a-purl-2",
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:*:some:package:2:*:*:*:*:*:*:*"),
|
||||
cpe.Must("cpe:2.3:*:some:package:2:*:*:*:*:*:*:*", cpe.GeneratedSource),
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -32,10 +32,17 @@ type PackageBasicData struct {
|
||||
Locations []file.Location `json:"locations"`
|
||||
Licenses licenses `json:"licenses"`
|
||||
Language pkg.Language `json:"language"`
|
||||
CPEs []string `json:"cpes"`
|
||||
CPEs cpes `json:"cpes"`
|
||||
PURL string `json:"purl"`
|
||||
}
|
||||
|
||||
type cpes []CPE
|
||||
|
||||
type CPE struct {
|
||||
Value string `json:"cpe"`
|
||||
Source string `json:"source,omitempty"`
|
||||
}
|
||||
|
||||
type licenses []License
|
||||
|
||||
type License struct {
|
||||
@@ -74,6 +81,29 @@ func (f *licenses) UnmarshalJSON(b []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func sourcedCPESfromSimpleCPEs(simpleCPEs []string) []CPE {
|
||||
var result []CPE
|
||||
for _, s := range simpleCPEs {
|
||||
result = append(result, CPE{
|
||||
Value: s,
|
||||
})
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (c *cpes) UnmarshalJSON(b []byte) error {
|
||||
var cs []CPE
|
||||
if err := json.Unmarshal(b, &cs); err != nil {
|
||||
var simpleCPEs []string
|
||||
if err := json.Unmarshal(b, &simpleCPEs); err != nil {
|
||||
return fmt.Errorf("unable to unmarshal cpes: %w", err)
|
||||
}
|
||||
cs = sourcedCPESfromSimpleCPEs(simpleCPEs)
|
||||
}
|
||||
*c = cs
|
||||
return nil
|
||||
}
|
||||
|
||||
// PackageCustomData contains ambiguous values (type-wise) from pkg.Package.
|
||||
type PackageCustomData struct {
|
||||
MetadataType string `json:"metadataType,omitempty"`
|
||||
|
||||
@@ -23,7 +23,9 @@
|
||||
],
|
||||
"language": "python",
|
||||
"cpes": [
|
||||
"cpe:2.3:*:some:package:2:*:*:*:*:*:*:*"
|
||||
{
|
||||
"cpe": "cpe:2.3:*:some:package:2:*:*:*:*:*:*:*"
|
||||
}
|
||||
],
|
||||
"purl": "a-purl-2",
|
||||
"metadataType": "python-package",
|
||||
@@ -56,7 +58,9 @@
|
||||
"licenses": [],
|
||||
"language": "",
|
||||
"cpes": [
|
||||
"cpe:2.3:*:some:package:2:*:*:*:*:*:*:*"
|
||||
{
|
||||
"cpe": "cpe:2.3:*:some:package:2:*:*:*:*:*:*:*"
|
||||
}
|
||||
],
|
||||
"purl": "pkg:deb/debian/package-2@2.0.1",
|
||||
"metadataType": "dpkg-db-entry",
|
||||
|
||||
@@ -23,7 +23,10 @@
|
||||
],
|
||||
"language": "python",
|
||||
"cpes": [
|
||||
"cpe:2.3:*:some:package:1:*:*:*:*:*:*:*"
|
||||
{
|
||||
"cpe": "cpe:2.3:*:some:package:1:*:*:*:*:*:*:*",
|
||||
"source": "nvd-cpe-dictionary"
|
||||
}
|
||||
],
|
||||
"purl": "a-purl-1",
|
||||
"metadataType": "python-package",
|
||||
@@ -51,7 +54,10 @@
|
||||
"licenses": [],
|
||||
"language": "",
|
||||
"cpes": [
|
||||
"cpe:2.3:*:some:package:2:*:*:*:*:*:*:*"
|
||||
{
|
||||
"cpe": "cpe:2.3:*:some:package:2:*:*:*:*:*:*:*",
|
||||
"source": "syft-generated"
|
||||
}
|
||||
],
|
||||
"purl": "a-purl-2",
|
||||
"metadataType": "dpkg-db-entry",
|
||||
|
||||
@@ -24,7 +24,10 @@
|
||||
],
|
||||
"language": "python",
|
||||
"cpes": [
|
||||
"cpe:2.3:*:some:package:1:*:*:*:*:*:*:*"
|
||||
{
|
||||
"cpe": "cpe:2.3:*:some:package:1:*:*:*:*:*:*:*",
|
||||
"source": "syft-generated"
|
||||
}
|
||||
],
|
||||
"purl": "a-purl-1",
|
||||
"metadataType": "python-package",
|
||||
@@ -53,7 +56,10 @@
|
||||
"licenses": [],
|
||||
"language": "",
|
||||
"cpes": [
|
||||
"cpe:2.3:*:some:package:2:*:*:*:*:*:*:*"
|
||||
{
|
||||
"cpe": "cpe:2.3:*:some:package:2:*:*:*:*:*:*:*",
|
||||
"source": "nvd-cpe-dictionary"
|
||||
}
|
||||
],
|
||||
"purl": "pkg:deb/debian/package-2@2.0.1",
|
||||
"metadataType": "dpkg-db-entry",
|
||||
|
||||
@@ -229,9 +229,13 @@ func toLicenseModel(pkgLicenses []pkg.License) (modelLicenses []model.License) {
|
||||
|
||||
// toPackageModel crates a new Package from the given pkg.Package.
|
||||
func toPackageModel(p pkg.Package, cfg EncoderConfig) model.Package {
|
||||
var cpes = make([]string, len(p.CPEs))
|
||||
var cpes = make([]model.CPE, len(p.CPEs))
|
||||
for i, c := range p.CPEs {
|
||||
cpes[i] = c.String()
|
||||
convertedCPE := model.CPE{
|
||||
Value: c.Attributes.String(),
|
||||
Source: c.Source.String(),
|
||||
}
|
||||
cpes[i] = convertedCPE
|
||||
}
|
||||
|
||||
// we want to make sure all catalogers are
|
||||
|
||||
@@ -301,9 +301,9 @@ func toSyftCatalog(pkgs []model.Package, idAliases map[string]string) *pkg.Colle
|
||||
func toSyftPackage(p model.Package, idAliases map[string]string) pkg.Package {
|
||||
var cpes []cpe.CPE
|
||||
for _, c := range p.CPEs {
|
||||
value, err := cpe.New(c)
|
||||
value, err := cpe.New(c.Value, cpe.Source(c.Source))
|
||||
if err != nil {
|
||||
log.Warnf("excluding invalid CPE %q: %v", c, err)
|
||||
log.Warnf("excluding invalid Attributes %q: %v", c, err)
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user