mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-12 07:40:48 -08:00
feat(cyclonedx): support dependency graph (#3177)
Co-authored-by: knqyf263 <knqyf263@gmail.com>
This commit is contained in:
@@ -57,8 +57,11 @@ func TestClientServer(t *testing.T) {
|
||||
name: "alpine 3.9 with high and critical severity",
|
||||
args: csArgs{
|
||||
IgnoreUnfixed: true,
|
||||
Severity: []string{"HIGH", "CRITICAL"},
|
||||
Input: "testdata/fixtures/images/alpine-39.tar.gz",
|
||||
Severity: []string{
|
||||
"HIGH",
|
||||
"CRITICAL",
|
||||
},
|
||||
Input: "testdata/fixtures/images/alpine-39.tar.gz",
|
||||
},
|
||||
golden: "testdata/alpine-39-high-critical.json.golden",
|
||||
},
|
||||
@@ -66,8 +69,11 @@ func TestClientServer(t *testing.T) {
|
||||
name: "alpine 3.9 with .trivyignore",
|
||||
args: csArgs{
|
||||
IgnoreUnfixed: false,
|
||||
IgnoreIDs: []string{"CVE-2019-1549", "CVE-2019-14697"},
|
||||
Input: "testdata/fixtures/images/alpine-39.tar.gz",
|
||||
IgnoreIDs: []string{
|
||||
"CVE-2019-1549",
|
||||
"CVE-2019-14697",
|
||||
},
|
||||
Input: "testdata/fixtures/images/alpine-39.tar.gz",
|
||||
},
|
||||
golden: "testdata/alpine-39-ignore-cveids.json.golden",
|
||||
},
|
||||
@@ -401,7 +407,6 @@ func TestClientServerWithCycloneDX(t *testing.T) {
|
||||
args csArgs
|
||||
wantComponentsCount int
|
||||
wantDependenciesCount int
|
||||
wantDependsOnCount []int
|
||||
}{
|
||||
{
|
||||
name: "fluentd with RubyGems with CycloneDX format",
|
||||
@@ -410,11 +415,7 @@ func TestClientServerWithCycloneDX(t *testing.T) {
|
||||
Input: "testdata/fixtures/images/fluentd-multiple-lockfiles.tar.gz",
|
||||
},
|
||||
wantComponentsCount: 161,
|
||||
wantDependenciesCount: 2,
|
||||
wantDependsOnCount: []int{
|
||||
105,
|
||||
56,
|
||||
},
|
||||
wantDependenciesCount: 80,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -437,9 +438,6 @@ func TestClientServerWithCycloneDX(t *testing.T) {
|
||||
|
||||
assert.EqualValues(t, tt.wantComponentsCount, len(lo.FromPtr(got.Components)))
|
||||
assert.EqualValues(t, tt.wantDependenciesCount, len(lo.FromPtr(got.Dependencies)))
|
||||
for i, dep := range *got.Dependencies {
|
||||
assert.EqualValues(t, tt.wantDependsOnCount[i], len(lo.FromPtr(dep.Dependencies)))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -577,9 +575,21 @@ func setup(t *testing.T, options setupOptions) (string, string) {
|
||||
}
|
||||
|
||||
func setupServer(addr, token, tokenHeader, cacheDir, cacheBackend string) []string {
|
||||
osArgs := []string{"--cache-dir", cacheDir, "server", "--skip-update", "--listen", addr}
|
||||
osArgs := []string{
|
||||
"--cache-dir",
|
||||
cacheDir,
|
||||
"server",
|
||||
"--skip-update",
|
||||
"--listen",
|
||||
addr,
|
||||
}
|
||||
if token != "" {
|
||||
osArgs = append(osArgs, []string{"--token", token, "--token-header", tokenHeader}...)
|
||||
osArgs = append(osArgs, []string{
|
||||
"--token",
|
||||
token,
|
||||
"--token-header",
|
||||
tokenHeader,
|
||||
}...)
|
||||
}
|
||||
if cacheBackend != "" {
|
||||
osArgs = append(osArgs, "--cache-backend", cacheBackend)
|
||||
@@ -595,7 +605,13 @@ func setupClient(t *testing.T, c csArgs, addr string, cacheDir string, golden st
|
||||
c.RemoteAddrOption = "--server"
|
||||
}
|
||||
t.Helper()
|
||||
osArgs := []string{"--cache-dir", cacheDir, c.Command, c.RemoteAddrOption, "http://" + addr}
|
||||
osArgs := []string{
|
||||
"--cache-dir",
|
||||
cacheDir,
|
||||
c.Command,
|
||||
c.RemoteAddrOption,
|
||||
"http://" + addr,
|
||||
}
|
||||
|
||||
if c.Format != "" {
|
||||
osArgs = append(osArgs, "--format", c.Format)
|
||||
|
||||
@@ -80,4 +80,4 @@
|
||||
}
|
||||
],
|
||||
"vulnerabilities": []
|
||||
}
|
||||
}
|
||||
@@ -134,6 +134,24 @@ func (pkgs Packages) Less(i, j int) bool {
|
||||
return pkgs[i].FilePath < pkgs[j].FilePath
|
||||
}
|
||||
|
||||
// ParentDeps returns a map where the keys are package IDs and the values are the packages
|
||||
// that depend on the respective package ID (parent dependencies).
|
||||
func (pkgs Packages) ParentDeps() map[string]Packages {
|
||||
parents := make(map[string]Packages)
|
||||
for _, pkg := range pkgs {
|
||||
for _, dependOn := range pkg.DependsOn {
|
||||
parents[dependOn] = append(parents[dependOn], pkg)
|
||||
}
|
||||
}
|
||||
|
||||
for k, v := range parents {
|
||||
parents[k] = lo.UniqBy(v, func(pkg Package) string {
|
||||
return pkg.ID
|
||||
})
|
||||
}
|
||||
return parents
|
||||
}
|
||||
|
||||
type SrcPackage struct {
|
||||
Name string `json:"name"`
|
||||
Version string `json:"version"`
|
||||
|
||||
@@ -146,7 +146,7 @@ func (r *vulnerabilityRenderer) countSeverities(vulns []types.DetectedVulnerabil
|
||||
|
||||
func (r *vulnerabilityRenderer) renderDependencyTree() {
|
||||
// Get parents of each dependency
|
||||
parents := reverseDeps(r.result.Packages)
|
||||
parents := ftypes.Packages(r.result.Packages).ParentDeps()
|
||||
if len(parents) == 0 {
|
||||
return
|
||||
}
|
||||
@@ -232,22 +232,6 @@ func addParents(topItem treeprint.Tree, pkg ftypes.Package, parentMap map[string
|
||||
}
|
||||
}
|
||||
|
||||
func reverseDeps(pkgs []ftypes.Package) map[string]ftypes.Packages {
|
||||
reversed := make(map[string]ftypes.Packages)
|
||||
for _, pkg := range pkgs {
|
||||
for _, dependOn := range pkg.DependsOn {
|
||||
reversed[dependOn] = append(reversed[dependOn], pkg)
|
||||
}
|
||||
}
|
||||
|
||||
for k, v := range reversed {
|
||||
reversed[k] = lo.UniqBy(v, func(pkg ftypes.Package) string {
|
||||
return pkg.ID
|
||||
})
|
||||
}
|
||||
return reversed
|
||||
}
|
||||
|
||||
func traverseAncestors(pkgs []ftypes.Package, parentMap map[string]ftypes.Packages) map[string][]string {
|
||||
ancestors := map[string][]string{}
|
||||
for _, pkg := range pkgs {
|
||||
|
||||
@@ -192,22 +192,32 @@ func externalRef(bomLink string, bomRef string) (string, error) {
|
||||
|
||||
func (e *Marshaler) marshalComponents(r types.Report, bomRef string) (*[]cdx.Component, *[]cdx.Dependency, *[]cdx.Vulnerability, error) {
|
||||
components := make([]cdx.Component, 0) // To export an empty array in JSON
|
||||
var dependencies []cdx.Dependency
|
||||
// we use map to avoid duplicate components
|
||||
dependencies := map[string]cdx.Dependency{}
|
||||
metadataDependencies := make([]string, 0) // To export an empty array in JSON
|
||||
libraryUniqMap := map[string]struct{}{}
|
||||
vulnMap := map[string]cdx.Vulnerability{}
|
||||
for _, result := range r.Results {
|
||||
bomRefMap := map[string]string{}
|
||||
var componentDependencies []string
|
||||
pkgIDToRef := map[string]string{}
|
||||
var directDepRefs []string
|
||||
|
||||
// Get dependency parents first
|
||||
parents := ftypes.Packages(result.Packages).ParentDeps()
|
||||
|
||||
for _, pkg := range result.Packages {
|
||||
pkgComponent, err := pkgToCdxComponent(result.Type, r.Metadata, pkg)
|
||||
if err != nil {
|
||||
return nil, nil, nil, xerrors.Errorf("failed to parse pkg: %w", err)
|
||||
}
|
||||
pkgID := packageID(result.Target, pkg.Name, utils.FormatVersion(pkg), pkg.FilePath)
|
||||
if _, ok := bomRefMap[pkgID]; !ok {
|
||||
bomRefMap[pkgID] = pkgComponent.BOMRef
|
||||
componentDependencies = append(componentDependencies, pkgComponent.BOMRef)
|
||||
bomRefMap[pkgID] = pkgComponent.BOMRef
|
||||
if pkg.ID != "" {
|
||||
pkgIDToRef[pkg.ID] = pkgComponent.BOMRef
|
||||
}
|
||||
// This package is a direct dependency
|
||||
if !pkg.Indirect || len(parents[pkg.ID]) == 0 {
|
||||
directDepRefs = append(directDepRefs, pkgComponent.BOMRef)
|
||||
}
|
||||
|
||||
// When multiple lock files have the same dependency with the same name and version,
|
||||
@@ -226,12 +236,30 @@ func (e *Marshaler) marshalComponents(r types.Report, bomRef string) (*[]cdx.Com
|
||||
|
||||
// For components
|
||||
// ref. https://cyclonedx.org/use-cases/#inventory
|
||||
//
|
||||
// TODO: All packages are flattened at the moment. We should construct dependency tree.
|
||||
components = append(components, pkgComponent)
|
||||
}
|
||||
}
|
||||
|
||||
// Iterate packages again to build dependency graph
|
||||
for _, pkg := range result.Packages {
|
||||
deps := lo.FilterMap(pkg.DependsOn, func(dep string, _ int) (string, bool) {
|
||||
if ref, ok := pkgIDToRef[dep]; ok {
|
||||
return ref, true
|
||||
}
|
||||
return "", false
|
||||
})
|
||||
if len(deps) == 0 {
|
||||
continue
|
||||
}
|
||||
sort.Strings(deps)
|
||||
ref := pkgIDToRef[pkg.ID]
|
||||
dependencies[ref] = cdx.Dependency{
|
||||
Ref: ref,
|
||||
Dependencies: &deps,
|
||||
}
|
||||
}
|
||||
sort.Strings(directDepRefs)
|
||||
|
||||
for _, vuln := range result.Vulnerabilities {
|
||||
// Take a bom-ref
|
||||
pkgID := packageID(result.Target, vuln.PkgName, vuln.InstalledVersion, vuln.PkgPath)
|
||||
@@ -260,7 +288,7 @@ func (e *Marshaler) marshalComponents(r types.Report, bomRef string) (*[]cdx.Com
|
||||
// ref. https://cyclonedx.org/use-cases/#inventory
|
||||
|
||||
// Dependency graph from #1 to #2
|
||||
metadataDependencies = append(metadataDependencies, componentDependencies...)
|
||||
metadataDependencies = append(metadataDependencies, directDepRefs...)
|
||||
} else if result.Class == types.ClassOSPkg || result.Class == types.ClassLangPkg {
|
||||
// If a package is OS package, it will be a dependency of "Operating System" component.
|
||||
// e.g.
|
||||
@@ -283,29 +311,29 @@ func (e *Marshaler) marshalComponents(r types.Report, bomRef string) (*[]cdx.Com
|
||||
components = append(components, resultComponent)
|
||||
|
||||
// Dependency graph from #2 to #3
|
||||
dependencies = append(dependencies,
|
||||
cdx.Dependency{
|
||||
Ref: resultComponent.BOMRef,
|
||||
Dependencies: &componentDependencies,
|
||||
},
|
||||
)
|
||||
|
||||
dependencies[resultComponent.BOMRef] = cdx.Dependency{
|
||||
Ref: resultComponent.BOMRef,
|
||||
Dependencies: &directDepRefs,
|
||||
}
|
||||
// Dependency graph from #1 to #2
|
||||
metadataDependencies = append(metadataDependencies, resultComponent.BOMRef)
|
||||
}
|
||||
}
|
||||
|
||||
vulns := maps.Values(vulnMap)
|
||||
sort.Slice(vulns, func(i, j int) bool {
|
||||
return vulns[i].ID > vulns[j].ID
|
||||
})
|
||||
|
||||
dependencies = append(dependencies,
|
||||
cdx.Dependency{
|
||||
Ref: bomRef,
|
||||
Dependencies: &metadataDependencies,
|
||||
},
|
||||
)
|
||||
return &components, &dependencies, &vulns, nil
|
||||
dependencies[bomRef] = cdx.Dependency{
|
||||
Ref: bomRef,
|
||||
Dependencies: &metadataDependencies,
|
||||
}
|
||||
dependencyList := maps.Values(dependencies)
|
||||
sort.Slice(dependencyList, func(i, j int) bool {
|
||||
return dependencyList[i].Ref < dependencyList[j].Ref
|
||||
})
|
||||
return &components, &dependencyList, &vulns, nil
|
||||
}
|
||||
|
||||
func packageID(target, pkgName, pkgVersion, pkgFilePath string) string {
|
||||
|
||||
@@ -57,6 +57,7 @@ func TestMarshaler_Marshal(t *testing.T) {
|
||||
Type: fos.CentOS,
|
||||
Packages: []ftypes.Package{
|
||||
{
|
||||
ID: "binutils@2.30-93.el8",
|
||||
Name: "binutils",
|
||||
Version: "2.30",
|
||||
Release: "93.el8",
|
||||
@@ -122,12 +123,17 @@ func TestMarshaler_Marshal(t *testing.T) {
|
||||
Type: ftypes.Bundler,
|
||||
Packages: []ftypes.Package{
|
||||
{
|
||||
ID: "actionpack@7.0.0",
|
||||
Name: "actionpack",
|
||||
Version: "7.0.0",
|
||||
},
|
||||
{
|
||||
ID: "actioncontroller@7.0.0",
|
||||
Name: "actioncontroller",
|
||||
Version: "7.0.0",
|
||||
DependsOn: []string{
|
||||
"actionpack@7.0.0",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -137,6 +143,7 @@ func TestMarshaler_Marshal(t *testing.T) {
|
||||
Type: ftypes.Bundler,
|
||||
Packages: []ftypes.Package{
|
||||
{
|
||||
ID: "actionpack@7.0.0",
|
||||
Name: "actionpack",
|
||||
Version: "7.0.0",
|
||||
},
|
||||
@@ -148,6 +155,7 @@ func TestMarshaler_Marshal(t *testing.T) {
|
||||
Type: ftypes.DotNetCore,
|
||||
Packages: []ftypes.Package{
|
||||
{
|
||||
ID: "Newtonsoft.Json@9.0.1",
|
||||
Name: "Newtonsoft.Json",
|
||||
Version: "9.0.1",
|
||||
},
|
||||
@@ -225,6 +233,10 @@ func TestMarshaler_Marshal(t *testing.T) {
|
||||
},
|
||||
PackageURL: "pkg:rpm/centos/binutils@2.30-93.el8?arch=aarch64&distro=centos-8.3.2011",
|
||||
Properties: &[]cdx.Property{
|
||||
{
|
||||
Name: "aquasecurity:trivy:PkgID",
|
||||
Value: "binutils@2.30-93.el8",
|
||||
},
|
||||
{
|
||||
Name: "aquasecurity:trivy:PkgType",
|
||||
Value: "centos",
|
||||
@@ -266,6 +278,10 @@ func TestMarshaler_Marshal(t *testing.T) {
|
||||
Version: "7.0.0",
|
||||
PackageURL: "pkg:gem/actionpack@7.0.0",
|
||||
Properties: &[]cdx.Property{
|
||||
{
|
||||
Name: "aquasecurity:trivy:PkgID",
|
||||
Value: "actionpack@7.0.0",
|
||||
},
|
||||
{
|
||||
Name: "aquasecurity:trivy:PkgType",
|
||||
Value: "bundler",
|
||||
@@ -279,6 +295,10 @@ func TestMarshaler_Marshal(t *testing.T) {
|
||||
Version: "7.0.0",
|
||||
PackageURL: "pkg:gem/actioncontroller@7.0.0",
|
||||
Properties: &[]cdx.Property{
|
||||
{
|
||||
Name: "aquasecurity:trivy:PkgID",
|
||||
Value: "actioncontroller@7.0.0",
|
||||
},
|
||||
{
|
||||
Name: "aquasecurity:trivy:PkgType",
|
||||
Value: "bundler",
|
||||
@@ -324,6 +344,10 @@ func TestMarshaler_Marshal(t *testing.T) {
|
||||
Version: "9.0.1",
|
||||
PackageURL: "pkg:nuget/Newtonsoft.Json@9.0.1",
|
||||
Properties: &[]cdx.Property{
|
||||
{
|
||||
Name: "aquasecurity:trivy:PkgID",
|
||||
Value: "Newtonsoft.Json@9.0.1",
|
||||
},
|
||||
{
|
||||
Name: "aquasecurity:trivy:PkgType",
|
||||
Value: "dotnet-core",
|
||||
@@ -386,8 +410,8 @@ func TestMarshaler_Marshal(t *testing.T) {
|
||||
{
|
||||
Ref: "3ff14136-e09f-4df9-80ea-000000000003",
|
||||
Dependencies: &[]string{
|
||||
"pkg:gem/actionpack@7.0.0",
|
||||
"pkg:gem/actioncontroller@7.0.0",
|
||||
"pkg:gem/actionpack@7.0.0",
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -408,6 +432,12 @@ func TestMarshaler_Marshal(t *testing.T) {
|
||||
"pkg:golang/golang.org/x/crypto@v0.0.0-20210421170649-83a5a9bb288b",
|
||||
},
|
||||
},
|
||||
{
|
||||
Ref: "pkg:gem/actioncontroller@7.0.0",
|
||||
Dependencies: &[]string{
|
||||
"pkg:gem/actionpack@7.0.0",
|
||||
},
|
||||
},
|
||||
{
|
||||
Ref: "pkg:oci/rails@sha256:a27fd8080b517143cbbbab9dfb7c8571c40d67d534bbdee55bd6c473f432b177?repository_url=index.docker.io%2Flibrary%2Frails&arch=arm64",
|
||||
Dependencies: &[]string{
|
||||
@@ -514,6 +544,7 @@ func TestMarshaler_Marshal(t *testing.T) {
|
||||
Type: fos.CentOS,
|
||||
Packages: []ftypes.Package{
|
||||
{
|
||||
ID: "acl@2.2.53-1.el8",
|
||||
Name: "acl",
|
||||
Version: "2.2.53",
|
||||
Release: "1.el8",
|
||||
@@ -525,6 +556,23 @@ func TestMarshaler_Marshal(t *testing.T) {
|
||||
SrcEpoch: 1,
|
||||
Modularitylabel: "",
|
||||
Licenses: []string{"GPLv2+"},
|
||||
DependsOn: []string{
|
||||
"glibc@2.28-151.el8",
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "glibc@2.28-151.el8",
|
||||
Name: "glibc",
|
||||
Version: "2.28",
|
||||
Release: "151.el8",
|
||||
Epoch: 0,
|
||||
Arch: "aarch64",
|
||||
SrcName: "glibc",
|
||||
SrcVersion: "2.28",
|
||||
SrcRelease: "151.el8",
|
||||
SrcEpoch: 0,
|
||||
Modularitylabel: "",
|
||||
Licenses: []string{"GPLv2+"},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -534,6 +582,7 @@ func TestMarshaler_Marshal(t *testing.T) {
|
||||
Type: ftypes.GemSpec,
|
||||
Packages: []ftypes.Package{
|
||||
{
|
||||
ID: "actionpack@7.0.0",
|
||||
Name: "actionpack",
|
||||
Version: "7.0.0",
|
||||
Layer: ftypes.Layer{
|
||||
@@ -542,6 +591,7 @@ func TestMarshaler_Marshal(t *testing.T) {
|
||||
FilePath: "tools/project-john/specifications/actionpack.gemspec",
|
||||
},
|
||||
{
|
||||
ID: "actionpack@7.0.1",
|
||||
Name: "actionpack",
|
||||
Version: "7.0.1",
|
||||
Layer: ftypes.Layer{
|
||||
@@ -690,6 +740,10 @@ func TestMarshaler_Marshal(t *testing.T) {
|
||||
},
|
||||
PackageURL: "pkg:rpm/centos/acl@2.2.53-1.el8?arch=aarch64&epoch=1&distro=centos-8.3.2011",
|
||||
Properties: &[]cdx.Property{
|
||||
{
|
||||
Name: "aquasecurity:trivy:PkgID",
|
||||
Value: "acl@2.2.53-1.el8",
|
||||
},
|
||||
{
|
||||
Name: "aquasecurity:trivy:PkgType",
|
||||
Value: "centos",
|
||||
@@ -712,6 +766,38 @@ func TestMarshaler_Marshal(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
BOMRef: "pkg:rpm/centos/glibc@2.28-151.el8?arch=aarch64&distro=centos-8.3.2011",
|
||||
Type: cdx.ComponentTypeLibrary,
|
||||
Name: "glibc",
|
||||
Version: "2.28-151.el8",
|
||||
Licenses: &cdx.Licenses{
|
||||
cdx.LicenseChoice{Expression: "GPLv2+"},
|
||||
},
|
||||
PackageURL: "pkg:rpm/centos/glibc@2.28-151.el8?arch=aarch64&distro=centos-8.3.2011",
|
||||
Properties: &[]cdx.Property{
|
||||
{
|
||||
Name: "aquasecurity:trivy:PkgID",
|
||||
Value: "glibc@2.28-151.el8",
|
||||
},
|
||||
{
|
||||
Name: "aquasecurity:trivy:PkgType",
|
||||
Value: "centos",
|
||||
},
|
||||
{
|
||||
Name: "aquasecurity:trivy:SrcName",
|
||||
Value: "glibc",
|
||||
},
|
||||
{
|
||||
Name: "aquasecurity:trivy:SrcVersion",
|
||||
Value: "2.28",
|
||||
},
|
||||
{
|
||||
Name: "aquasecurity:trivy:SrcRelease",
|
||||
Value: "151.el8",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
BOMRef: "3ff14136-e09f-4df9-80ea-000000000003",
|
||||
Type: cdx.ComponentTypeOS,
|
||||
@@ -735,6 +821,10 @@ func TestMarshaler_Marshal(t *testing.T) {
|
||||
Version: "7.0.0",
|
||||
PackageURL: "pkg:gem/actionpack@7.0.0",
|
||||
Properties: &[]cdx.Property{
|
||||
{
|
||||
Name: "aquasecurity:trivy:PkgID",
|
||||
Value: "actionpack@7.0.0",
|
||||
},
|
||||
{
|
||||
Name: "aquasecurity:trivy:PkgType",
|
||||
Value: "gemspec",
|
||||
@@ -756,6 +846,10 @@ func TestMarshaler_Marshal(t *testing.T) {
|
||||
Version: "7.0.1",
|
||||
PackageURL: "pkg:gem/actionpack@7.0.1",
|
||||
Properties: &[]cdx.Property{
|
||||
{
|
||||
Name: "aquasecurity:trivy:PkgID",
|
||||
Value: "actionpack@7.0.1",
|
||||
},
|
||||
{
|
||||
Name: "aquasecurity:trivy:PkgType",
|
||||
Value: "gemspec",
|
||||
@@ -772,12 +866,6 @@ func TestMarshaler_Marshal(t *testing.T) {
|
||||
},
|
||||
},
|
||||
Dependencies: &[]cdx.Dependency{
|
||||
{
|
||||
Ref: "3ff14136-e09f-4df9-80ea-000000000003",
|
||||
Dependencies: &[]string{
|
||||
"pkg:rpm/centos/acl@2.2.53-1.el8?arch=aarch64&epoch=1&distro=centos-8.3.2011",
|
||||
},
|
||||
},
|
||||
{
|
||||
Ref: "3ff14136-e09f-4df9-80ea-000000000002",
|
||||
Dependencies: &[]string{
|
||||
@@ -786,6 +874,20 @@ func TestMarshaler_Marshal(t *testing.T) {
|
||||
"pkg:gem/actionpack@7.0.1?file_path=tools%2Fproject-doe%2Fspecifications%2Factionpack.gemspec",
|
||||
},
|
||||
},
|
||||
{
|
||||
Ref: "3ff14136-e09f-4df9-80ea-000000000003",
|
||||
Dependencies: &[]string{
|
||||
"pkg:rpm/centos/acl@2.2.53-1.el8?arch=aarch64&epoch=1&distro=centos-8.3.2011",
|
||||
// Trivy is unable to identify the direct OS packages as of today.
|
||||
"pkg:rpm/centos/glibc@2.28-151.el8?arch=aarch64&distro=centos-8.3.2011",
|
||||
},
|
||||
},
|
||||
{
|
||||
Ref: "pkg:rpm/centos/acl@2.2.53-1.el8?arch=aarch64&epoch=1&distro=centos-8.3.2011",
|
||||
Dependencies: &[]string{
|
||||
"pkg:rpm/centos/glibc@2.28-151.el8?arch=aarch64&distro=centos-8.3.2011",
|
||||
},
|
||||
},
|
||||
},
|
||||
Vulnerabilities: &[]cdx.Vulnerability{
|
||||
{
|
||||
@@ -944,18 +1046,18 @@ func TestMarshaler_Marshal(t *testing.T) {
|
||||
},
|
||||
Vulnerabilities: &[]cdx.Vulnerability{},
|
||||
Dependencies: &[]cdx.Dependency{
|
||||
{
|
||||
Ref: "3ff14136-e09f-4df9-80ea-000000000003",
|
||||
Dependencies: &[]string{
|
||||
"pkg:gem/actioncable@6.1.4.1",
|
||||
},
|
||||
},
|
||||
{
|
||||
Ref: "3ff14136-e09f-4df9-80ea-000000000002",
|
||||
Dependencies: &[]string{
|
||||
"3ff14136-e09f-4df9-80ea-000000000003",
|
||||
},
|
||||
},
|
||||
{
|
||||
Ref: "3ff14136-e09f-4df9-80ea-000000000003",
|
||||
Dependencies: &[]string{
|
||||
"pkg:gem/actioncable@6.1.4.1",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -972,6 +1074,7 @@ func TestMarshaler_Marshal(t *testing.T) {
|
||||
Type: ftypes.NodePkg,
|
||||
Packages: []ftypes.Package{
|
||||
{
|
||||
ID: "ruby-typeprof@0.20.1",
|
||||
Name: "ruby-typeprof",
|
||||
Version: "0.20.1",
|
||||
Licenses: []string{"MIT"},
|
||||
@@ -1022,6 +1125,10 @@ func TestMarshaler_Marshal(t *testing.T) {
|
||||
cdx.LicenseChoice{Expression: "MIT"},
|
||||
},
|
||||
Properties: &[]cdx.Property{
|
||||
{
|
||||
Name: "aquasecurity:trivy:PkgID",
|
||||
Value: "ruby-typeprof@0.20.1",
|
||||
},
|
||||
{
|
||||
Name: "aquasecurity:trivy:PkgType",
|
||||
Value: "node-pkg",
|
||||
@@ -1108,7 +1215,6 @@ func TestMarshaler_Marshal(t *testing.T) {
|
||||
marshaler := cyclonedx.NewMarshaler("dev", cyclonedx.WithClock(clock), cyclonedx.WithNewUUID(newUUID))
|
||||
got, err := marshaler.Marshal(tt.inputReport)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user