diff --git a/internal/task/package_task_factory.go b/internal/task/package_task_factory.go index 5a65a29f0..d3215f663 100644 --- a/internal/task/package_task_factory.go +++ b/internal/task/package_task_factory.go @@ -110,6 +110,8 @@ func NewPackageTask(cfg CatalogingFactoryConfig, c pkg.Cataloger, tags ...string pkgs, relationships = applyCompliance(cfg.ComplianceConfig, pkgs, relationships) + finalizeDependencyCompleteness(pkgs) + sbom.AddPackages(pkgs...) sbom.AddRelationships(relationships...) t.Add(int64(len(pkgs))) @@ -124,6 +126,13 @@ func NewPackageTask(cfg CatalogingFactoryConfig, c pkg.Cataloger, tags ...string return NewTask(c.Name(), fn, tags...) } +func finalizeDependencyCompleteness(pkgs []pkg.Package) { + // ensure that all packages have a non-empty dependency list + for i := range pkgs { + pkgs[i].Dependencies = pkg.ParseDependencyCompleteness(string(pkgs[i].Dependencies)) + } +} + func finalizePkgCatalogerResults(cfg CatalogingFactoryConfig, resolver file.PathResolver, catalogerName string, pkgs []pkg.Package, relationships []artifact.Relationship) ([]pkg.Package, []artifact.Relationship) { for i, p := range pkgs { if p.FoundBy == "" { diff --git a/syft/pkg/cataloger/alpine/cataloger_test.go b/syft/pkg/cataloger/alpine/cataloger_test.go index fff8e77f4..f1a0738ec 100644 --- a/syft/pkg/cataloger/alpine/cataloger_test.go +++ b/syft/pkg/cataloger/alpine/cataloger_test.go @@ -23,7 +23,8 @@ func TestApkDBCataloger(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("GPL-3.0-or-later", dbLocation), ), - Locations: file.NewLocationSet(dbLocation), + Locations: file.NewLocationSet(dbLocation), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.ApkDBEntry{ Package: "bash", OriginPackage: "bash", @@ -52,7 +53,8 @@ func TestApkDBCataloger(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("GPL-2.0-only", dbLocation), ), - Locations: file.NewLocationSet(dbLocation), + Locations: file.NewLocationSet(dbLocation), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.ApkDBEntry{ Package: "busybox-binsh", OriginPackage: "busybox", @@ -81,7 +83,8 @@ func TestApkDBCataloger(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("MIT", dbLocation), ), - Locations: file.NewLocationSet(dbLocation), + Locations: file.NewLocationSet(dbLocation), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.ApkDBEntry{ Package: "musl", OriginPackage: "musl", @@ -108,7 +111,8 @@ func TestApkDBCataloger(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("GPL-2.0-or-later", dbLocation), ), - Locations: file.NewLocationSet(dbLocation), + Locations: file.NewLocationSet(dbLocation), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.ApkDBEntry{ Package: "readline", OriginPackage: "readline", diff --git a/syft/pkg/cataloger/alpine/package.go b/syft/pkg/cataloger/alpine/package.go index 69c8a8d18..89041553a 100644 --- a/syft/pkg/cataloger/alpine/package.go +++ b/syft/pkg/cataloger/alpine/package.go @@ -20,13 +20,14 @@ func newPackage(d parsedData, release *linux.Release, dbLocation file.Location) } p := pkg.Package{ - Name: d.Package, - Version: d.Version, - Locations: file.NewLocationSet(dbLocation.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), - Licenses: pkg.NewLicenseSet(pkg.NewLicensesFromLocation(dbLocation, licenseStrings...)...), - PURL: packageURL(d.ApkDBEntry, release), - Type: pkg.ApkPkg, - Metadata: d.ApkDBEntry, + Name: d.Package, + Version: d.Version, + Locations: file.NewLocationSet(dbLocation.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), + Licenses: pkg.NewLicenseSet(pkg.NewLicensesFromLocation(dbLocation, licenseStrings...)...), + PURL: packageURL(d.ApkDBEntry, release), + Type: pkg.ApkPkg, + Dependencies: pkg.CompleteDependencies, + Metadata: d.ApkDBEntry, } p.SetID() diff --git a/syft/pkg/cataloger/alpine/parse_apk_db_test.go b/syft/pkg/cataloger/alpine/parse_apk_db_test.go index 7918f38f6..be2523fad 100644 --- a/syft/pkg/cataloger/alpine/parse_apk_db_test.go +++ b/syft/pkg/cataloger/alpine/parse_apk_db_test.go @@ -90,7 +90,8 @@ func TestSinglePackageDetails(t *testing.T) { pkg.NewLicense("BSD"), pkg.NewLicense("GPL2+"), ), - Type: pkg.ApkPkg, + Type: pkg.ApkPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.ApkDBEntry{ Package: "musl-utils", OriginPackage: "musl", @@ -177,7 +178,8 @@ func TestSinglePackageDetails(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicense("GPL-2.0-only"), ), - Type: pkg.ApkPkg, + Type: pkg.ApkPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.ApkDBEntry{ Package: "alpine-baselayout-data", OriginPackage: "alpine-baselayout", @@ -221,8 +223,8 @@ func TestSinglePackageDetails(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicense("GPL-2.0-only"), ), - Type: pkg.ApkPkg, - PURL: "", + Type: pkg.ApkPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.ApkDBEntry{ Package: "alpine-baselayout", OriginPackage: "alpine-baselayout", diff --git a/syft/pkg/cataloger/arch/cataloger_test.go b/syft/pkg/cataloger/arch/cataloger_test.go index e61525246..919fa1b6d 100644 --- a/syft/pkg/cataloger/arch/cataloger_test.go +++ b/syft/pkg/cataloger/arch/cataloger_test.go @@ -34,7 +34,8 @@ func TestAlpmCataloger(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("MIT", treeSitterDbLocation), ), - Locations: file.NewLocationSet(treeSitterDbLocation), + Locations: file.NewLocationSet(treeSitterDbLocation), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.AlpmDBEntry{ BasePackage: "tree-sitter", Package: "tree-sitter", @@ -60,7 +61,8 @@ func TestAlpmCataloger(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("GPL3", emacsDbLocation), ), - Locations: file.NewLocationSet(emacsDbLocation), + Locations: file.NewLocationSet(emacsDbLocation), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.AlpmDBEntry{ BasePackage: "emacs", Package: "emacs", @@ -86,6 +88,7 @@ func TestAlpmCataloger(t *testing.T) { fuzzyDbLocation, file.NewLocation("var/lib/pacman/local/fuzzy-1.2-3/files"), ), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.AlpmDBEntry{ Package: "fuzzy", Version: "1.2-3", @@ -103,11 +106,12 @@ func TestAlpmCataloger(t *testing.T) { } madeupPkg := pkg.Package{ - Name: "madeup", - Version: "20.30-4", - Type: pkg.AlpmPkg, - FoundBy: "alpm-db-cataloger", - Locations: file.NewLocationSet(madeupDbLocation), + Name: "madeup", + Version: "20.30-4", + Type: pkg.AlpmPkg, + FoundBy: "alpm-db-cataloger", + Locations: file.NewLocationSet(madeupDbLocation), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.AlpmDBEntry{ Package: "madeup", Version: "20.30-4", @@ -131,6 +135,7 @@ func TestAlpmCataloger(t *testing.T) { file.NewLocation("var/lib/pacman/local/gmp-6.2.1-2/files"), file.NewLocation("var/lib/pacman/local/gmp-6.2.1-2/mtree"), ), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.AlpmDBEntry{ BasePackage: "gmp", Package: "gmp", diff --git a/syft/pkg/cataloger/arch/package.go b/syft/pkg/cataloger/arch/package.go index 88b557c76..9bb36ff1d 100644 --- a/syft/pkg/cataloger/arch/package.go +++ b/syft/pkg/cataloger/arch/package.go @@ -16,13 +16,14 @@ func newPackage(m *parsedData, release *linux.Release, dbLocation file.Location, locs.Add(otherLocations...) p := pkg.Package{ - Name: m.Package, - Version: m.Version, - Locations: locs, - Licenses: pkg.NewLicenseSet(pkg.NewLicensesFromLocation(dbLocation.WithoutAnnotations(), licenseCandidates...)...), - Type: pkg.AlpmPkg, - PURL: packageURL(m, release), - Metadata: m.AlpmDBEntry, + Name: m.Package, + Version: m.Version, + Locations: locs, + Licenses: pkg.NewLicenseSet(pkg.NewLicensesFromLocation(dbLocation.WithoutAnnotations(), licenseCandidates...)...), + Type: pkg.AlpmPkg, + PURL: packageURL(m, release), + Dependencies: pkg.CompleteDependencies, + Metadata: m.AlpmDBEntry, } p.SetID() diff --git a/syft/pkg/cataloger/binary/classifier_package.go b/syft/pkg/cataloger/binary/classifier_package.go index a2ed4ab6d..9b68775bf 100644 --- a/syft/pkg/cataloger/binary/classifier_package.go +++ b/syft/pkg/cataloger/binary/classifier_package.go @@ -35,6 +35,9 @@ func newClassifierPackage(classifier Classifier, location file.Location, matchMe Type: pkg.BinaryPkg, CPEs: cpes, FoundBy: catalogerName, + // classifiers are limited to identifying package identities, but have no information about dependencies. + // Furthermore, we have no understanding about the mechanisms for dependency resolution for these packages. + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.BinarySignature{ Matches: []pkg.ClassifierMatch{ { diff --git a/syft/pkg/cataloger/binary/elf_package.go b/syft/pkg/cataloger/binary/elf_package.go index 81e4384d1..47fa8d472 100644 --- a/syft/pkg/cataloger/binary/elf_package.go +++ b/syft/pkg/cataloger/binary/elf_package.go @@ -16,7 +16,10 @@ func newELFPackage(metadata elfBinaryPackageNotes, locations file.LocationSet) p PURL: packageURL(metadata), Type: pkgType(metadata.Type), Locations: locations, - Metadata: metadata.ELFBinaryPackageNoteJSONPayload, + // though we can look for shared libs, we cannot see static dependencies nor dynamic dependencies using dlopen. + // this means that, even in cases where the dep info is actually complete, we can't programmatically determine that. + Dependencies: pkg.IncompleteDependencies, + Metadata: metadata.ELFBinaryPackageNoteJSONPayload, } p.SetID() diff --git a/syft/pkg/cataloger/binary/elf_package_cataloger_test.go b/syft/pkg/cataloger/binary/elf_package_cataloger_test.go index 0325b3083..221b386dd 100644 --- a/syft/pkg/cataloger/binary/elf_package_cataloger_test.go +++ b/syft/pkg/cataloger/binary/elf_package_cataloger_test.go @@ -35,7 +35,8 @@ func Test_ELF_Package_Cataloger(t *testing.T) { pkg.License{Value: "MIT", SPDXExpression: "MIT", Type: "declared"}, ), - Type: pkg.BinaryPkg, + Type: pkg.BinaryPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.ELFBinaryPackageNoteJSONPayload{ Type: "testfixture", Vendor: "syft", @@ -56,7 +57,8 @@ func Test_ELF_Package_Cataloger(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.License{Value: "MIT", SPDXExpression: "MIT", Type: "declared"}, ), - Type: pkg.BinaryPkg, + Type: pkg.BinaryPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.ELFBinaryPackageNoteJSONPayload{ Type: "testfixture", Vendor: "syft", @@ -80,8 +82,9 @@ func Test_ELF_Package_Cataloger(t *testing.T) { file.NewLocation("/sha256sum").WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), file.NewLocation("/sha1sum").WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), - Licenses: pkg.NewLicenseSet(), - Type: pkg.RpmPkg, + Licenses: pkg.NewLicenseSet(), + Type: pkg.RpmPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.ELFBinaryPackageNoteJSONPayload{ Type: "rpm", Architecture: "x86_64", @@ -102,8 +105,9 @@ func Test_ELF_Package_Cataloger(t *testing.T) { file.NewLocation("/sha256sum").WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), file.NewLocation("/sha1sum").WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), - Licenses: pkg.NewLicenseSet(), - Type: pkg.RpmPkg, + Licenses: pkg.NewLicenseSet(), + Type: pkg.RpmPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.ELFBinaryPackageNoteJSONPayload{ Type: "rpm", Architecture: "arm", diff --git a/syft/pkg/cataloger/binary/elf_package_test.go b/syft/pkg/cataloger/binary/elf_package_test.go index 689e259d1..f57ab8118 100644 --- a/syft/pkg/cataloger/binary/elf_package_test.go +++ b/syft/pkg/cataloger/binary/elf_package_test.go @@ -154,10 +154,11 @@ func Test_newELFPackage(t *testing.T) { }, expected: pkg.Package{ - Name: "syfttestfixture", - Version: "0.01", - Type: "binary", - PURL: "pkg:generic/syftsys/syfttestfixture@0.01", + Name: "syfttestfixture", + Version: "0.01", + Type: "binary", + PURL: "pkg:generic/syftsys/syfttestfixture@0.01", + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.ELFBinaryPackageNoteJSONPayload{ Type: "binary", System: "syftsys", diff --git a/syft/pkg/cataloger/cpp/package.go b/syft/pkg/cataloger/cpp/package.go index bc003ea7f..0e7c06d5f 100644 --- a/syft/pkg/cataloger/cpp/package.go +++ b/syft/pkg/cataloger/cpp/package.go @@ -67,35 +67,43 @@ func splitConanRef(ref string) *conanRef { } func newConanfilePackage(m pkg.ConanfileEntry, locations ...file.Location) *pkg.Package { - return newConanPackage(m.Ref, m, locations...) + // though a conanfile is a listing of direct dependencies, we are not capturing these today, so are forced to answer incomplete + return newConanPackage(m.Ref, m, pkg.IncompleteDependencies, locations...) } -func newConanlockPackage(m pkg.ConanV1LockEntry, locations ...file.Location) *pkg.Package { - return newConanPackage(m.Ref, m, locations...) +func newConanlockV1Package(m pkg.ConanV1LockEntry, locations ...file.Location) *pkg.Package { + // conan.lock is primarily used to lock the dependency graph at specific versions to ensure consistent builds, + // and the dependency tree can be inferred from the contents (distinguishing between direct and transitive dependencies) + return newConanPackage(m.Ref, m, pkg.CompleteDependencies, locations...) } -func newConanReferencePackage(m pkg.ConanV2LockEntry, locations ...file.Location) *pkg.Package { - return newConanPackage(m.Ref, m, locations...) +func newConanLockv2Package(m pkg.ConanV2LockEntry, locations ...file.Location) *pkg.Package { + // conan.lock is primarily used to lock the dependency graph at specific versions to ensure consistent builds, + // and the dependency tree can be inferred from the contents (distinguishing between direct and transitive dependencies) + return newConanPackage(m.Ref, m, pkg.CompleteDependencies, locations...) } func newConaninfoPackage(m pkg.ConaninfoEntry, locations ...file.Location) *pkg.Package { - return newConanPackage(m.Ref, m, locations...) + // conaninfo.txt is generated during the build and contains detailed information about the entire dependency tree, + // and today the codebase does infer direct dependencies from this source + return newConanPackage(m.Ref, m, pkg.CompleteDependencies, locations...) } -func newConanPackage(refStr string, metadata any, locations ...file.Location) *pkg.Package { +func newConanPackage(refStr string, metadata any, dep pkg.DependencyCompleteness, locations ...file.Location) *pkg.Package { ref := splitConanRef(refStr) if ref == nil { return nil } p := pkg.Package{ - Name: ref.Name, - Version: ref.Version, - Locations: file.NewLocationSet(locations...), - PURL: packageURL(ref), - Language: pkg.CPP, - Type: pkg.ConanPkg, - Metadata: metadata, + Name: ref.Name, + Version: ref.Version, + Locations: file.NewLocationSet(locations...), + PURL: packageURL(ref), + Language: pkg.CPP, + Type: pkg.ConanPkg, + Dependencies: dep, + Metadata: metadata, } p.SetID() diff --git a/syft/pkg/cataloger/cpp/parse_conanfile.go b/syft/pkg/cataloger/cpp/parse_conanfile.go index 2885b6f71..eb5f2f6e3 100644 --- a/syft/pkg/cataloger/cpp/parse_conanfile.go +++ b/syft/pkg/cataloger/cpp/parse_conanfile.go @@ -22,11 +22,12 @@ func parseConanfile(_ context.Context, _ file.Resolver, _ *generic.Environment, r := bufio.NewReader(reader) inRequirements := false var pkgs []pkg.Package +loop: for { line, err := r.ReadString('\n') switch { case errors.Is(err, io.EOF): - return pkgs, nil, unknown.IfEmptyf(pkgs, "unable to determine packages") + break loop case err != nil: return nil, nil, fmt.Errorf("failed to parse conanfile.txt file: %w", err) } @@ -56,4 +57,5 @@ func parseConanfile(_ context.Context, _ file.Resolver, _ *generic.Environment, pkgs = append(pkgs, *p) } + return pkgs, nil, unknown.IfEmptyf(pkgs, "unable to determine packages") } diff --git a/syft/pkg/cataloger/cpp/parse_conanfile_test.go b/syft/pkg/cataloger/cpp/parse_conanfile_test.go index 65a4b9b0d..03fd5c367 100644 --- a/syft/pkg/cataloger/cpp/parse_conanfile_test.go +++ b/syft/pkg/cataloger/cpp/parse_conanfile_test.go @@ -14,67 +14,73 @@ func TestParseConanfile(t *testing.T) { fixtureLocationSet := file.NewLocationSet(file.NewLocation(fixture)) expected := []pkg.Package{ { - Name: "catch2", - Version: "2.13.8", - PURL: "pkg:conan/catch2@2.13.8", - Locations: fixtureLocationSet, - Language: pkg.CPP, - Type: pkg.ConanPkg, + Name: "catch2", + Version: "2.13.8", + PURL: "pkg:conan/catch2@2.13.8", + Locations: fixtureLocationSet, + Language: pkg.CPP, + Type: pkg.ConanPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.ConanfileEntry{ Ref: "catch2/2.13.8", }, }, { - Name: "docopt.cpp", - Version: "0.6.3", - PURL: "pkg:conan/docopt.cpp@0.6.3", - Locations: fixtureLocationSet, - Language: pkg.CPP, - Type: pkg.ConanPkg, + Name: "docopt.cpp", + Version: "0.6.3", + PURL: "pkg:conan/docopt.cpp@0.6.3", + Locations: fixtureLocationSet, + Language: pkg.CPP, + Type: pkg.ConanPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.ConanfileEntry{ Ref: "docopt.cpp/0.6.3", }, }, { - Name: "fmt", - Version: "8.1.1", - PURL: "pkg:conan/fmt@8.1.1", - Locations: fixtureLocationSet, - Language: pkg.CPP, - Type: pkg.ConanPkg, + Name: "fmt", + Version: "8.1.1", + PURL: "pkg:conan/fmt@8.1.1", + Locations: fixtureLocationSet, + Language: pkg.CPP, + Type: pkg.ConanPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.ConanfileEntry{ Ref: "fmt/8.1.1", }, }, { - Name: "spdlog", - Version: "1.9.2", - PURL: "pkg:conan/my_user/spdlog@1.9.2?channel=my_channel", - Locations: fixtureLocationSet, - Language: pkg.CPP, - Type: pkg.ConanPkg, + Name: "spdlog", + Version: "1.9.2", + PURL: "pkg:conan/my_user/spdlog@1.9.2?channel=my_channel", + Locations: fixtureLocationSet, + Language: pkg.CPP, + Type: pkg.ConanPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.ConanfileEntry{ Ref: "spdlog/1.9.2@my_user/my_channel#1234567%%987654", }, }, { - Name: "sdl", - Version: "2.0.20", - PURL: "pkg:conan/sdl@2.0.20", - Locations: fixtureLocationSet, - Language: pkg.CPP, - Type: pkg.ConanPkg, + Name: "sdl", + Version: "2.0.20", + PURL: "pkg:conan/sdl@2.0.20", + Locations: fixtureLocationSet, + Language: pkg.CPP, + Type: pkg.ConanPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.ConanfileEntry{ Ref: "sdl/2.0.20#1234567%%987654", }, }, { - Name: "fltk", - Version: "1.3.8", - PURL: "pkg:conan/my_user/fltk@1.3.8?channel=my_channel", - Locations: fixtureLocationSet, - Language: pkg.CPP, - Type: pkg.ConanPkg, + Name: "fltk", + Version: "1.3.8", + PURL: "pkg:conan/my_user/fltk@1.3.8?channel=my_channel", + Locations: fixtureLocationSet, + Language: pkg.CPP, + Type: pkg.ConanPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.ConanfileEntry{ Ref: "fltk/1.3.8@my_user/my_channel", }, diff --git a/syft/pkg/cataloger/cpp/parse_conaninfo_test.go b/syft/pkg/cataloger/cpp/parse_conaninfo_test.go index 3c7eb1bac..9f12b0905 100644 --- a/syft/pkg/cataloger/cpp/parse_conaninfo_test.go +++ b/syft/pkg/cataloger/cpp/parse_conaninfo_test.go @@ -13,72 +13,78 @@ func TestParseConaninfo(t *testing.T) { fixture := "test-fixtures/conaninfo/mfast/1.2.2/my_user/my_channel/package/9d1f076b471417647c2022a78d5e2c1f834289ac/conaninfo.txt" expected := []pkg.Package{ { - Name: "mfast", - Version: "1.2.2", - PURL: "pkg:conan/my_user/mfast@1.2.2?channel=my_channel", - Locations: file.NewLocationSet(file.NewLocation(fixture)), - Language: pkg.CPP, - Type: pkg.ConanPkg, + Name: "mfast", + Version: "1.2.2", + PURL: "pkg:conan/my_user/mfast@1.2.2?channel=my_channel", + Locations: file.NewLocationSet(file.NewLocation(fixture)), + Language: pkg.CPP, + Type: pkg.ConanPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.ConaninfoEntry{ Ref: "mfast/1.2.2@my_user/my_channel#c6f6387c9b99780f0ee05e25f99d0f39", PackageID: "9d1f076b471417647c2022a78d5e2c1f834289ac", }, }, { - Name: "boost", - Version: "1.75.0", - PURL: "pkg:conan/boost@1.75.0", - Locations: file.NewLocationSet(file.NewLocation(fixture)), - Language: pkg.CPP, - Type: pkg.ConanPkg, + Name: "boost", + Version: "1.75.0", + PURL: "pkg:conan/boost@1.75.0", + Locations: file.NewLocationSet(file.NewLocation(fixture)), + Language: pkg.CPP, + Type: pkg.ConanPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.ConaninfoEntry{ Ref: "boost/1.75.0:dc8aedd23a0f0a773a5fcdcfe1ae3e89c4205978", PackageID: "dc8aedd23a0f0a773a5fcdcfe1ae3e89c4205978", }, }, { - Name: "zlib", - Version: "1.2.13", - PURL: "pkg:conan/zlib@1.2.13", - Locations: file.NewLocationSet(file.NewLocation(fixture)), - Language: pkg.CPP, - Type: pkg.ConanPkg, + Name: "zlib", + Version: "1.2.13", + PURL: "pkg:conan/zlib@1.2.13", + Locations: file.NewLocationSet(file.NewLocation(fixture)), + Language: pkg.CPP, + Type: pkg.ConanPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.ConaninfoEntry{ Ref: "zlib/1.2.13:dfbe50feef7f3c6223a476cd5aeadb687084a646", PackageID: "dfbe50feef7f3c6223a476cd5aeadb687084a646", }, }, { - Name: "bzip2", - Version: "1.0.8", - PURL: "pkg:conan/bzip2@1.0.8", - Locations: file.NewLocationSet(file.NewLocation(fixture)), - Language: pkg.CPP, - Type: pkg.ConanPkg, + Name: "bzip2", + Version: "1.0.8", + PURL: "pkg:conan/bzip2@1.0.8", + Locations: file.NewLocationSet(file.NewLocation(fixture)), + Language: pkg.CPP, + Type: pkg.ConanPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.ConaninfoEntry{ Ref: "bzip2/1.0.8:c32092bf4d4bb47cf962af898e02823f499b017e", PackageID: "c32092bf4d4bb47cf962af898e02823f499b017e", }, }, { - Name: "libbacktrace", - Version: "cci.20210118", - PURL: "pkg:conan/libbacktrace@cci.20210118", - Locations: file.NewLocationSet(file.NewLocation(fixture)), - Language: pkg.CPP, - Type: pkg.ConanPkg, + Name: "libbacktrace", + Version: "cci.20210118", + PURL: "pkg:conan/libbacktrace@cci.20210118", + Locations: file.NewLocationSet(file.NewLocation(fixture)), + Language: pkg.CPP, + Type: pkg.ConanPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.ConaninfoEntry{ Ref: "libbacktrace/cci.20210118:dfbe50feef7f3c6223a476cd5aeadb687084a646", PackageID: "dfbe50feef7f3c6223a476cd5aeadb687084a646", }, }, { - Name: "tinyxml2", - Version: "9.0.0", - PURL: "pkg:conan/tinyxml2@9.0.0", - Locations: file.NewLocationSet(file.NewLocation(fixture)), - Language: pkg.CPP, - Type: pkg.ConanPkg, + Name: "tinyxml2", + Version: "9.0.0", + PURL: "pkg:conan/tinyxml2@9.0.0", + Locations: file.NewLocationSet(file.NewLocation(fixture)), + Language: pkg.CPP, + Type: pkg.ConanPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.ConaninfoEntry{ Ref: "tinyxml2/9.0.0:6557f18ca99c0b6a233f43db00e30efaa525e27e", PackageID: "6557f18ca99c0b6a233f43db00e30efaa525e27e", diff --git a/syft/pkg/cataloger/cpp/parse_conanlock.go b/syft/pkg/cataloger/cpp/parse_conanlock.go index 1a1aa4d12..cf2ab9e52 100644 --- a/syft/pkg/cataloger/cpp/parse_conanlock.go +++ b/syft/pkg/cataloger/cpp/parse_conanlock.go @@ -89,7 +89,7 @@ func handleConanLockV1(cl conanLock, reader file.LocationReadCloser, parsedPkgRe Prev: node.Prev, } - p := newConanlockPackage( + p := newConanlockV1Package( metadata, reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ) @@ -113,7 +113,7 @@ func handleConanLockV2(cl conanLock, reader file.LocationReadCloser, indexToPkgM continue } - p := newConanReferencePackage( + p := newConanLockv2Package( reference, reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ) diff --git a/syft/pkg/cataloger/cpp/parse_conanlock_test.go b/syft/pkg/cataloger/cpp/parse_conanlock_test.go index 23fe24c28..628e471b1 100644 --- a/syft/pkg/cataloger/cpp/parse_conanlock_test.go +++ b/syft/pkg/cataloger/cpp/parse_conanlock_test.go @@ -13,12 +13,13 @@ func TestParseConanLock(t *testing.T) { fixture := "test-fixtures/conan.lock" expected := []pkg.Package{ { - Name: "mfast", - Version: "1.2.2", - PURL: "pkg:conan/my_user/mfast@1.2.2?channel=my_channel", - Locations: file.NewLocationSet(file.NewLocation(fixture)), - Language: pkg.CPP, - Type: pkg.ConanPkg, + Name: "mfast", + Version: "1.2.2", + PURL: "pkg:conan/my_user/mfast@1.2.2?channel=my_channel", + Locations: file.NewLocationSet(file.NewLocation(fixture)), + Language: pkg.CPP, + Type: pkg.ConanPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.ConanV1LockEntry{ Ref: "mfast/1.2.2@my_user/my_channel#c6f6387c9b99780f0ee05e25f99d0f39", Options: pkg.KeyValues{ @@ -104,12 +105,13 @@ func TestParseConanLock(t *testing.T) { }, }, { - Name: "boost", - Version: "1.75.0", - PURL: "pkg:conan/boost@1.75.0", - Locations: file.NewLocationSet(file.NewLocation(fixture)), - Language: pkg.CPP, - Type: pkg.ConanPkg, + Name: "boost", + Version: "1.75.0", + PURL: "pkg:conan/boost@1.75.0", + Locations: file.NewLocationSet(file.NewLocation(fixture)), + Language: pkg.CPP, + Type: pkg.ConanPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.ConanV1LockEntry{ Ref: "boost/1.75.0#a9c318f067216f900900e044e7af4ab1", Options: pkg.KeyValues{ @@ -190,12 +192,13 @@ func TestParseConanLock(t *testing.T) { }, }, { - Name: "zlib", - Version: "1.2.12", - PURL: "pkg:conan/zlib@1.2.12", - Locations: file.NewLocationSet(file.NewLocation(fixture)), - Language: pkg.CPP, - Type: pkg.ConanPkg, + Name: "zlib", + Version: "1.2.12", + PURL: "pkg:conan/zlib@1.2.12", + Locations: file.NewLocationSet(file.NewLocation(fixture)), + Language: pkg.CPP, + Type: pkg.ConanPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.ConanV1LockEntry{ Ref: "zlib/1.2.12#c67ce17f2e96b972d42393ce50a76a1a", Options: pkg.KeyValues{ @@ -214,12 +217,13 @@ func TestParseConanLock(t *testing.T) { }, }, { - Name: "bzip2", - Version: "1.0.8", - PURL: "pkg:conan/bzip2@1.0.8", - Locations: file.NewLocationSet(file.NewLocation(fixture)), - Language: pkg.CPP, - Type: pkg.ConanPkg, + Name: "bzip2", + Version: "1.0.8", + PURL: "pkg:conan/bzip2@1.0.8", + Locations: file.NewLocationSet(file.NewLocation(fixture)), + Language: pkg.CPP, + Type: pkg.ConanPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.ConanV1LockEntry{ Ref: "bzip2/1.0.8#62a8031289639043797cf53fa876d0ef", Options: []pkg.KeyValue{ @@ -242,12 +246,13 @@ func TestParseConanLock(t *testing.T) { }, }, { - Name: "libbacktrace", - Version: "cci.20210118", - PURL: "pkg:conan/libbacktrace@cci.20210118", - Locations: file.NewLocationSet(file.NewLocation(fixture)), - Language: pkg.CPP, - Type: pkg.ConanPkg, + Name: "libbacktrace", + Version: "cci.20210118", + PURL: "pkg:conan/libbacktrace@cci.20210118", + Locations: file.NewLocationSet(file.NewLocation(fixture)), + Language: pkg.CPP, + Type: pkg.ConanPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.ConanV1LockEntry{ Ref: "libbacktrace/cci.20210118#76e40b760e0bcd602d46db56b22820ab", Options: []pkg.KeyValue{ @@ -266,12 +271,13 @@ func TestParseConanLock(t *testing.T) { }, }, { - Name: "tinyxml2", - Version: "9.0.0", - PURL: "pkg:conan/tinyxml2@9.0.0", - Locations: file.NewLocationSet(file.NewLocation(fixture)), - Language: pkg.CPP, - Type: pkg.ConanPkg, + Name: "tinyxml2", + Version: "9.0.0", + PURL: "pkg:conan/tinyxml2@9.0.0", + Locations: file.NewLocationSet(file.NewLocation(fixture)), + Language: pkg.CPP, + Type: pkg.ConanPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.ConanV1LockEntry{ Ref: "tinyxml2/9.0.0#9f13a36ebfc222cd55fe531a0a8d94d1", Options: []pkg.KeyValue{ @@ -337,12 +343,13 @@ func TestParseConanLockV2(t *testing.T) { fixture := "test-fixtures/conanlock-v2/conan.lock" expected := []pkg.Package{ { - Name: "matrix", - Version: "1.1", - PURL: "pkg:conan/matrix@1.1", - Locations: file.NewLocationSet(file.NewLocation(fixture)), - Language: pkg.CPP, - Type: pkg.ConanPkg, + Name: "matrix", + Version: "1.1", + PURL: "pkg:conan/matrix@1.1", + Locations: file.NewLocationSet(file.NewLocation(fixture)), + Language: pkg.CPP, + Type: pkg.ConanPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.ConanV2LockEntry{ Ref: "matrix/1.1#905c3f0babc520684c84127378fefdd0%1675278901.7527816", RecipeRevision: "905c3f0babc520684c84127378fefdd0", @@ -350,12 +357,13 @@ func TestParseConanLockV2(t *testing.T) { }, }, { - Name: "sound32", - Version: "1.0", - PURL: "pkg:conan/sound32@1.0", - Locations: file.NewLocationSet(file.NewLocation(fixture)), - Language: pkg.CPP, - Type: pkg.ConanPkg, + Name: "sound32", + Version: "1.0", + PURL: "pkg:conan/sound32@1.0", + Locations: file.NewLocationSet(file.NewLocation(fixture)), + Language: pkg.CPP, + Type: pkg.ConanPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.ConanV2LockEntry{ Ref: "sound32/1.0#83d4b7bf607b3b60a6546f8b58b5cdd7%1675278904.0791488", RecipeRevision: "83d4b7bf607b3b60a6546f8b58b5cdd7", diff --git a/syft/pkg/cataloger/dart/package.go b/syft/pkg/cataloger/dart/package.go index 99fad4133..54fab06e2 100644 --- a/syft/pkg/cataloger/dart/package.go +++ b/syft/pkg/cataloger/dart/package.go @@ -21,7 +21,9 @@ func newPubspecLockPackage(name string, raw pubspecLockPackage, locations ...fil PURL: packageURL(metadata), Language: pkg.Dart, Type: pkg.DartPubPkg, - Metadata: metadata, + // since we capture no dependencies today we know that the dep info is incomplete + Dependencies: pkg.IncompleteDependencies, + Metadata: metadata, } p.SetID() diff --git a/syft/pkg/cataloger/dart/parse_pubspec_lock_test.go b/syft/pkg/cataloger/dart/parse_pubspec_lock_test.go index 5aa5fc702..79e3d794e 100644 --- a/syft/pkg/cataloger/dart/parse_pubspec_lock_test.go +++ b/syft/pkg/cataloger/dart/parse_pubspec_lock_test.go @@ -14,12 +14,13 @@ func TestParsePubspecLock(t *testing.T) { fixtureLocationSet := file.NewLocationSet(file.NewLocation(fixture)) expected := []pkg.Package{ { - Name: "ale", - Version: "3.3.0", - PURL: "pkg:pub/ale@3.3.0?hosted_url=pub.hosted.org", - Locations: fixtureLocationSet, - Language: pkg.Dart, - Type: pkg.DartPubPkg, + Name: "ale", + Version: "3.3.0", + PURL: "pkg:pub/ale@3.3.0?hosted_url=pub.hosted.org", + Locations: fixtureLocationSet, + Language: pkg.Dart, + Type: pkg.DartPubPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.DartPubspecLockEntry{ Name: "ale", Version: "3.3.0", @@ -27,72 +28,78 @@ func TestParsePubspecLock(t *testing.T) { }, }, { - Name: "analyzer", - Version: "0.40.7", - PURL: "pkg:pub/analyzer@0.40.7", - Locations: fixtureLocationSet, - Language: pkg.Dart, - Type: pkg.DartPubPkg, + Name: "analyzer", + Version: "0.40.7", + PURL: "pkg:pub/analyzer@0.40.7", + Locations: fixtureLocationSet, + Language: pkg.Dart, + Type: pkg.DartPubPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.DartPubspecLockEntry{ Name: "analyzer", Version: "0.40.7", }, }, { - Name: "ansicolor", - Version: "1.1.1", - PURL: "pkg:pub/ansicolor@1.1.1", - Locations: fixtureLocationSet, - Language: pkg.Dart, - Type: pkg.DartPubPkg, + Name: "ansicolor", + Version: "1.1.1", + PURL: "pkg:pub/ansicolor@1.1.1", + Locations: fixtureLocationSet, + Language: pkg.Dart, + Type: pkg.DartPubPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.DartPubspecLockEntry{ Name: "ansicolor", Version: "1.1.1", }, }, { - Name: "archive", - Version: "2.0.13", - PURL: "pkg:pub/archive@2.0.13", - Locations: fixtureLocationSet, - Language: pkg.Dart, - Type: pkg.DartPubPkg, + Name: "archive", + Version: "2.0.13", + PURL: "pkg:pub/archive@2.0.13", + Locations: fixtureLocationSet, + Language: pkg.Dart, + Type: pkg.DartPubPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.DartPubspecLockEntry{ Name: "archive", Version: "2.0.13", }, }, { - Name: "args", - Version: "1.6.0", - PURL: "pkg:pub/args@1.6.0", - Locations: fixtureLocationSet, - Language: pkg.Dart, - Type: pkg.DartPubPkg, + Name: "args", + Version: "1.6.0", + PURL: "pkg:pub/args@1.6.0", + Locations: fixtureLocationSet, + Language: pkg.Dart, + Type: pkg.DartPubPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.DartPubspecLockEntry{ Name: "args", Version: "1.6.0", }, }, { - Name: "flutter", - Version: "0.0.0", - PURL: "pkg:pub/flutter@0.0.0", - Locations: fixtureLocationSet, - Language: pkg.Dart, - Type: pkg.DartPubPkg, + Name: "flutter", + Version: "0.0.0", + PURL: "pkg:pub/flutter@0.0.0", + Locations: fixtureLocationSet, + Language: pkg.Dart, + Type: pkg.DartPubPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.DartPubspecLockEntry{ Name: "flutter", Version: "0.0.0", }, }, { - Name: "key_binder", - Version: "1.11.20", - PURL: "pkg:pub/key_binder@1.11.20?vcs_url=git%40github.com:Workiva/key_binder.git%403f7b3a6350e73c7dcac45301c0e18fbd42af02f7", - Locations: fixtureLocationSet, - Language: pkg.Dart, - Type: pkg.DartPubPkg, + Name: "key_binder", + Version: "1.11.20", + PURL: "pkg:pub/key_binder@1.11.20?vcs_url=git%40github.com:Workiva/key_binder.git%403f7b3a6350e73c7dcac45301c0e18fbd42af02f7", + Locations: fixtureLocationSet, + Language: pkg.Dart, + Type: pkg.DartPubPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.DartPubspecLockEntry{ Name: "key_binder", Version: "1.11.20", diff --git a/syft/pkg/cataloger/debian/cataloger_test.go b/syft/pkg/cataloger/debian/cataloger_test.go index 299d7338d..40ed0bcf3 100644 --- a/syft/pkg/cataloger/debian/cataloger_test.go +++ b/syft/pkg/cataloger/debian/cataloger_test.go @@ -36,7 +36,8 @@ func TestDpkgCataloger(t *testing.T) { file.NewLocation("/var/lib/dpkg/info/libpam-runtime.conffiles"), file.NewLocation("/usr/share/doc/libpam-runtime/copyright"), ), - Type: pkg.DebPkg, + Type: pkg.DebPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.DpkgDBEntry{ Package: "libpam-runtime", Source: "pam", @@ -109,7 +110,8 @@ func TestDpkgCataloger(t *testing.T) { file.NewLocation("/var/lib/dpkg/status.d/libsqlite3-0.preinst"), file.NewLocation("/usr/share/doc/libsqlite3-0/copyright"), ), - Type: pkg.DebPkg, + Type: pkg.DebPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.DpkgDBEntry{ Package: "libsqlite3-0", Source: "sqlite3", diff --git a/syft/pkg/cataloger/debian/package.go b/syft/pkg/cataloger/debian/package.go index db93ba8eb..3b1d24b66 100644 --- a/syft/pkg/cataloger/debian/package.go +++ b/syft/pkg/cataloger/debian/package.go @@ -30,13 +30,14 @@ func newDpkgPackage(d pkg.DpkgDBEntry, dbLocation file.Location, resolver file.R locations.Add(evidence...) p := pkg.Package{ - Name: d.Package, - Version: d.Version, - Licenses: pkg.NewLicenseSet(licenses...), - Locations: locations, - PURL: packageURL(d, release), - Type: pkg.DebPkg, - Metadata: d, + Name: d.Package, + Version: d.Version, + Licenses: pkg.NewLicenseSet(licenses...), + Locations: locations, + PURL: packageURL(d, release), + Type: pkg.DebPkg, + Dependencies: pkg.CompleteDependencies, + Metadata: d, } if resolver != nil { diff --git a/syft/pkg/cataloger/debian/parse_dpkg_db_test.go b/syft/pkg/cataloger/debian/parse_dpkg_db_test.go index 50ab3485b..6a4b99436 100644 --- a/syft/pkg/cataloger/debian/parse_dpkg_db_test.go +++ b/syft/pkg/cataloger/debian/parse_dpkg_db_test.go @@ -349,11 +349,12 @@ Installed-Size: 10kib `, want: []pkg.Package{ { - Name: "apt", - Type: "deb", - PURL: "pkg:deb/debian/apt?distro=debian-10", - Licenses: pkg.NewLicenseSet(), - Locations: file.NewLocationSet(file.NewLocation("place")), + Name: "apt", + Type: "deb", + PURL: "pkg:deb/debian/apt?distro=debian-10", + Licenses: pkg.NewLicenseSet(), + Locations: file.NewLocationSet(file.NewLocation("place")), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.DpkgDBEntry{ Package: "apt", InstalledSize: 10240, diff --git a/syft/pkg/cataloger/dotnet/package.go b/syft/pkg/cataloger/dotnet/package.go index 0d1563cd7..6c59f089c 100644 --- a/syft/pkg/cataloger/dotnet/package.go +++ b/syft/pkg/cataloger/dotnet/package.go @@ -22,13 +22,14 @@ func newDotnetDepsPackage(nameVersion string, lib dotnetDepsLibrary, locations . } p := &pkg.Package{ - Name: name, - Version: version, - Locations: file.NewLocationSet(locations...), - PURL: packageURL(m), - Language: pkg.Dotnet, - Type: pkg.DotnetPkg, - Metadata: m, + Name: name, + Version: version, + Locations: file.NewLocationSet(locations...), + PURL: packageURL(m), + Language: pkg.Dotnet, + Type: pkg.DotnetPkg, + Dependencies: pkg.CompleteDependencies, + Metadata: m, } p.SetID() diff --git a/syft/pkg/cataloger/dotnet/parse_dotnet_deps_test.go b/syft/pkg/cataloger/dotnet/parse_dotnet_deps_test.go index 84878c86c..20f81ae9c 100644 --- a/syft/pkg/cataloger/dotnet/parse_dotnet_deps_test.go +++ b/syft/pkg/cataloger/dotnet/parse_dotnet_deps_test.go @@ -20,36 +20,39 @@ func TestParseDotnetDeps(t *testing.T) { fixture := "test-fixtures/TestLibrary.deps.json" fixtureLocationSet := file.NewLocationSet(file.NewLocation(fixture)) rootPkg := pkg.Package{ - Name: "TestLibrary", - Version: "1.0.0", - PURL: "pkg:nuget/TestLibrary@1.0.0", - Locations: fixtureLocationSet, - Language: pkg.Dotnet, - Type: pkg.DotnetPkg, + Name: "TestLibrary", + Version: "1.0.0", + PURL: "pkg:nuget/TestLibrary@1.0.0", + Locations: fixtureLocationSet, + Language: pkg.Dotnet, + Type: pkg.DotnetPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.DotnetDepsEntry{ Name: "TestLibrary", Version: "1.0.0", }, } testCommon := pkg.Package{ - Name: "TestCommon", - Version: "1.0.0", - PURL: "pkg:nuget/TestCommon@1.0.0", - Locations: fixtureLocationSet, - Language: pkg.Dotnet, - Type: pkg.DotnetPkg, + Name: "TestCommon", + Version: "1.0.0", + PURL: "pkg:nuget/TestCommon@1.0.0", + Locations: fixtureLocationSet, + Language: pkg.Dotnet, + Type: pkg.DotnetPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.DotnetDepsEntry{ Name: "TestCommon", Version: "1.0.0", }, } awssdkcore := pkg.Package{ - Name: "AWSSDK.Core", - Version: "3.7.10.6", - PURL: "pkg:nuget/AWSSDK.Core@3.7.10.6", - Locations: fixtureLocationSet, - Language: pkg.Dotnet, - Type: pkg.DotnetPkg, + Name: "AWSSDK.Core", + Version: "3.7.10.6", + PURL: "pkg:nuget/AWSSDK.Core@3.7.10.6", + Locations: fixtureLocationSet, + Language: pkg.Dotnet, + Type: pkg.DotnetPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.DotnetDepsEntry{ Name: "AWSSDK.Core", Version: "3.7.10.6", @@ -59,12 +62,13 @@ func TestParseDotnetDeps(t *testing.T) { }, } msftDependencyInjectionAbstractions := pkg.Package{ - Name: "Microsoft.Extensions.DependencyInjection.Abstractions", - Version: "6.0.0", - PURL: "pkg:nuget/Microsoft.Extensions.DependencyInjection.Abstractions@6.0.0", - Locations: fixtureLocationSet, - Language: pkg.Dotnet, - Type: pkg.DotnetPkg, + Name: "Microsoft.Extensions.DependencyInjection.Abstractions", + Version: "6.0.0", + PURL: "pkg:nuget/Microsoft.Extensions.DependencyInjection.Abstractions@6.0.0", + Locations: fixtureLocationSet, + Language: pkg.Dotnet, + Type: pkg.DotnetPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.DotnetDepsEntry{ Name: "Microsoft.Extensions.DependencyInjection.Abstractions", Version: "6.0.0", @@ -74,12 +78,13 @@ func TestParseDotnetDeps(t *testing.T) { }, } msftDependencyInjection := pkg.Package{ - Name: "Microsoft.Extensions.DependencyInjection", - Version: "6.0.0", - PURL: "pkg:nuget/Microsoft.Extensions.DependencyInjection@6.0.0", - Locations: fixtureLocationSet, - Language: pkg.Dotnet, - Type: pkg.DotnetPkg, + Name: "Microsoft.Extensions.DependencyInjection", + Version: "6.0.0", + PURL: "pkg:nuget/Microsoft.Extensions.DependencyInjection@6.0.0", + Locations: fixtureLocationSet, + Language: pkg.Dotnet, + Type: pkg.DotnetPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.DotnetDepsEntry{ Name: "Microsoft.Extensions.DependencyInjection", Version: "6.0.0", @@ -89,12 +94,13 @@ func TestParseDotnetDeps(t *testing.T) { }, } msftLoggingAbstractions := pkg.Package{ - Name: "Microsoft.Extensions.Logging.Abstractions", - Version: "6.0.0", - PURL: "pkg:nuget/Microsoft.Extensions.Logging.Abstractions@6.0.0", - Locations: fixtureLocationSet, - Language: pkg.Dotnet, - Type: pkg.DotnetPkg, + Name: "Microsoft.Extensions.Logging.Abstractions", + Version: "6.0.0", + PURL: "pkg:nuget/Microsoft.Extensions.Logging.Abstractions@6.0.0", + Locations: fixtureLocationSet, + Language: pkg.Dotnet, + Type: pkg.DotnetPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.DotnetDepsEntry{ Name: "Microsoft.Extensions.Logging.Abstractions", Version: "6.0.0", @@ -104,12 +110,13 @@ func TestParseDotnetDeps(t *testing.T) { }, } msftExtensionsLogging := pkg.Package{ - Name: "Microsoft.Extensions.Logging", - Version: "6.0.0", - PURL: "pkg:nuget/Microsoft.Extensions.Logging@6.0.0", - Locations: fixtureLocationSet, - Language: pkg.Dotnet, - Type: pkg.DotnetPkg, + Name: "Microsoft.Extensions.Logging", + Version: "6.0.0", + PURL: "pkg:nuget/Microsoft.Extensions.Logging@6.0.0", + Locations: fixtureLocationSet, + Language: pkg.Dotnet, + Type: pkg.DotnetPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.DotnetDepsEntry{ Name: "Microsoft.Extensions.Logging", Version: "6.0.0", @@ -119,12 +126,13 @@ func TestParseDotnetDeps(t *testing.T) { }, } msftExtensionsOptions := pkg.Package{ - Name: "Microsoft.Extensions.Options", - Version: "6.0.0", - PURL: "pkg:nuget/Microsoft.Extensions.Options@6.0.0", - Locations: fixtureLocationSet, - Language: pkg.Dotnet, - Type: pkg.DotnetPkg, + Name: "Microsoft.Extensions.Options", + Version: "6.0.0", + PURL: "pkg:nuget/Microsoft.Extensions.Options@6.0.0", + Locations: fixtureLocationSet, + Language: pkg.Dotnet, + Type: pkg.DotnetPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.DotnetDepsEntry{ Name: "Microsoft.Extensions.Options", Version: "6.0.0", @@ -134,12 +142,13 @@ func TestParseDotnetDeps(t *testing.T) { }, } msftExtensionsPrimitives := pkg.Package{ - Name: "Microsoft.Extensions.Primitives", - Version: "6.0.0", - PURL: "pkg:nuget/Microsoft.Extensions.Primitives@6.0.0", - Locations: fixtureLocationSet, - Language: pkg.Dotnet, - Type: pkg.DotnetPkg, + Name: "Microsoft.Extensions.Primitives", + Version: "6.0.0", + PURL: "pkg:nuget/Microsoft.Extensions.Primitives@6.0.0", + Locations: fixtureLocationSet, + Language: pkg.Dotnet, + Type: pkg.DotnetPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.DotnetDepsEntry{ Name: "Microsoft.Extensions.Primitives", Version: "6.0.0", @@ -149,12 +158,13 @@ func TestParseDotnetDeps(t *testing.T) { }, } newtonsoftJson := pkg.Package{ - Name: "Newtonsoft.Json", - Version: "13.0.1", - PURL: "pkg:nuget/Newtonsoft.Json@13.0.1", - Locations: fixtureLocationSet, - Language: pkg.Dotnet, - Type: pkg.DotnetPkg, + Name: "Newtonsoft.Json", + Version: "13.0.1", + PURL: "pkg:nuget/Newtonsoft.Json@13.0.1", + Locations: fixtureLocationSet, + Language: pkg.Dotnet, + Type: pkg.DotnetPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.DotnetDepsEntry{ Name: "Newtonsoft.Json", Version: "13.0.1", @@ -164,12 +174,13 @@ func TestParseDotnetDeps(t *testing.T) { }, } serilogSinksConsole := pkg.Package{ - Name: "Serilog.Sinks.Console", - Version: "4.0.1", - PURL: "pkg:nuget/Serilog.Sinks.Console@4.0.1", - Locations: fixtureLocationSet, - Language: pkg.Dotnet, - Type: pkg.DotnetPkg, + Name: "Serilog.Sinks.Console", + Version: "4.0.1", + PURL: "pkg:nuget/Serilog.Sinks.Console@4.0.1", + Locations: fixtureLocationSet, + Language: pkg.Dotnet, + Type: pkg.DotnetPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.DotnetDepsEntry{ Name: "Serilog.Sinks.Console", Version: "4.0.1", @@ -179,12 +190,13 @@ func TestParseDotnetDeps(t *testing.T) { }, } serilog := pkg.Package{ - Name: "Serilog", - Version: "2.10.0", - PURL: "pkg:nuget/Serilog@2.10.0", - Locations: fixtureLocationSet, - Language: pkg.Dotnet, - Type: pkg.DotnetPkg, + Name: "Serilog", + Version: "2.10.0", + PURL: "pkg:nuget/Serilog@2.10.0", + Locations: fixtureLocationSet, + Language: pkg.Dotnet, + Type: pkg.DotnetPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.DotnetDepsEntry{ Name: "Serilog", Version: "2.10.0", @@ -194,12 +206,13 @@ func TestParseDotnetDeps(t *testing.T) { }, } systemDiagnosticsDiagnosticsource := pkg.Package{ - Name: "System.Diagnostics.DiagnosticSource", - Version: "6.0.0", - PURL: "pkg:nuget/System.Diagnostics.DiagnosticSource@6.0.0", - Locations: fixtureLocationSet, - Language: pkg.Dotnet, - Type: pkg.DotnetPkg, + Name: "System.Diagnostics.DiagnosticSource", + Version: "6.0.0", + PURL: "pkg:nuget/System.Diagnostics.DiagnosticSource@6.0.0", + Locations: fixtureLocationSet, + Language: pkg.Dotnet, + Type: pkg.DotnetPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.DotnetDepsEntry{ Name: "System.Diagnostics.DiagnosticSource", Version: "6.0.0", @@ -209,12 +222,13 @@ func TestParseDotnetDeps(t *testing.T) { }, } systemRuntimeCompilerServicesUnsafe := pkg.Package{ - Name: "System.Runtime.CompilerServices.Unsafe", - Version: "6.0.0", - PURL: "pkg:nuget/System.Runtime.CompilerServices.Unsafe@6.0.0", - Locations: fixtureLocationSet, - Language: pkg.Dotnet, - Type: pkg.DotnetPkg, + Name: "System.Runtime.CompilerServices.Unsafe", + Version: "6.0.0", + PURL: "pkg:nuget/System.Runtime.CompilerServices.Unsafe@6.0.0", + Locations: fixtureLocationSet, + Language: pkg.Dotnet, + Type: pkg.DotnetPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.DotnetDepsEntry{ Name: "System.Runtime.CompilerServices.Unsafe", Version: "6.0.0", diff --git a/syft/pkg/cataloger/dotnet/parse_dotnet_portable_executable.go b/syft/pkg/cataloger/dotnet/parse_dotnet_portable_executable.go index 4ea4d1c18..6e3fac79b 100644 --- a/syft/pkg/cataloger/dotnet/parse_dotnet_portable_executable.go +++ b/syft/pkg/cataloger/dotnet/parse_dotnet_portable_executable.go @@ -9,7 +9,7 @@ import ( "github.com/saferwall/pe" - version "github.com/anchore/go-version" + "github.com/anchore/go-version" "github.com/anchore/packageurl-go" "github.com/anchore/syft/internal/log" "github.com/anchore/syft/syft/artifact" @@ -44,7 +44,7 @@ func parseDotnetPortableExecutable(_ context.Context, _ file.Resolver, _ *generi return nil, nil, fmt.Errorf("unable to parse version resources in PE file: %w", err) } - dotNetPkg, err := buildDotNetPackage(versionResources, f) + dotNetPkg, err := buildDotNetPEPackage(versionResources, f) if err != nil { log.Tracef("unable to build dotnet package for: %v %v", f.RealPath, err) return nil, nil, err @@ -53,14 +53,14 @@ func parseDotnetPortableExecutable(_ context.Context, _ file.Resolver, _ *generi return []pkg.Package{dotNetPkg}, nil, nil } -func buildDotNetPackage(versionResources map[string]string, f file.LocationReadCloser) (dnpkg pkg.Package, err error) { +func buildDotNetPEPackage(versionResources map[string]string, f file.LocationReadCloser) (dnpkg pkg.Package, err error) { name := findName(versionResources) if name == "" { return dnpkg, fmt.Errorf("unable to find PE name in file") } - version := findVersion(versionResources) - if version == "" { + ver := findVersion(versionResources) + if ver == "" { return dnpkg, fmt.Errorf("unable to find PE version in file") } @@ -76,12 +76,14 @@ func buildDotNetPackage(versionResources map[string]string, f file.LocationReadC dnpkg = pkg.Package{ Name: name, - Version: version, + Version: ver, Locations: file.NewLocationSet(f.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), Type: pkg.DotnetPkg, Language: pkg.Dotnet, - PURL: portableExecutablePackageURL(name, version), - Metadata: metadata, + PURL: portableExecutablePackageURL(name, ver), + // by nature PE metadata does not have any dependency information, thus we are forced to claim incomplete + Dependencies: pkg.IncompleteDependencies, + Metadata: metadata, } dnpkg.SetID() diff --git a/syft/pkg/cataloger/dotnet/parse_dotnet_portable_executable_test.go b/syft/pkg/cataloger/dotnet/parse_dotnet_portable_executable_test.go index 2be417d6a..9c73c11f4 100644 --- a/syft/pkg/cataloger/dotnet/parse_dotnet_portable_executable_test.go +++ b/syft/pkg/cataloger/dotnet/parse_dotnet_portable_executable_test.go @@ -32,8 +32,9 @@ func TestParseDotnetPortableExecutable(t *testing.T) { "Assembly Version": "3.14.2.11", }, expectedPackage: pkg.Package{ - Name: "Active Directory Authentication Library", - Version: "3.14.40721.0918", + Name: "Active Directory Authentication Library", + Version: "3.14.40721.0918", + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.DotnetPortableExecutableEntry{ AssemblyVersion: "3.14.2.11", LegalCopyright: "Copyright (c) Microsoft Corporation. All rights reserved.", @@ -57,9 +58,10 @@ func TestParseDotnetPortableExecutable(t *testing.T) { "ProductVersion": "4.6.25512.01 built by: dlab-DDVSOWINAGE016. Commit Hash: d0d5c7b49271cadb6d97de26d8e623e98abdc8db", }, expectedPackage: pkg.Package{ - Name: "äbFileVersi on", - Version: "4.6.25512.01", - PURL: "pkg:nuget/%C3%A4bFileVersi%20on@4.6.25512.01", + Name: "äbFileVersi on", + Version: "4.6.25512.01", + PURL: "pkg:nuget/%C3%A4bFileVersi%20on@4.6.25512.01", + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.DotnetPortableExecutableEntry{ LegalCopyright: "© Microsoft Corporation. All rights reserved.", InternalName: "äb\x01FileVersion", @@ -82,8 +84,9 @@ func TestParseDotnetPortableExecutable(t *testing.T) { "ProductVersion": "4.7.3190.0", }, expectedPackage: pkg.Package{ - Name: "System.Data.Linq.dll", - Version: "4.7.3190.0", + Name: "System.Data.Linq.dll", + Version: "4.7.3190.0", + Dependencies: pkg.IncompleteDependencies, }, }, { @@ -99,8 +102,9 @@ func TestParseDotnetPortableExecutable(t *testing.T) { "ProductVersion": "8.4.0", }, expectedPackage: pkg.Package{ - Name: "The curl executable", - Version: "8.4.0", + Name: "The curl executable", + Version: "8.4.0", + Dependencies: pkg.IncompleteDependencies, }, }, { @@ -116,8 +120,9 @@ func TestParseDotnetPortableExecutable(t *testing.T) { "ProductVersion": "8.0.1", }, expectedPackage: pkg.Package{ - Name: "Prometheus.AspNetCore.dll", - Version: "8.0.1", + Name: "Prometheus.AspNetCore.dll", + Version: "8.0.1", + Dependencies: pkg.IncompleteDependencies, }, }, { @@ -132,8 +137,9 @@ func TestParseDotnetPortableExecutable(t *testing.T) { "ProductVersion": "1, 0, 0, 0", }, expectedPackage: pkg.Package{ - Name: "Hidden Input", - Version: "1, 0, 0, 0", + Name: "Hidden Input", + Version: "1, 0, 0, 0", + Dependencies: pkg.IncompleteDependencies, }, }, { @@ -148,8 +154,9 @@ func TestParseDotnetPortableExecutable(t *testing.T) { "ProductVersion": "3.23.2", }, expectedPackage: pkg.Package{ - Name: "SQLite", - Version: "3.23.2", + Name: "SQLite", + Version: "3.23.2", + Dependencies: pkg.IncompleteDependencies, }, }, { @@ -165,8 +172,9 @@ func TestParseDotnetPortableExecutable(t *testing.T) { "ProductVersion": "80.1.7.92", }, expectedPackage: pkg.Package{ - Name: "Brave Browser", - Version: "80.1.7.92", + Name: "Brave Browser", + Version: "80.1.7.92", + Dependencies: pkg.IncompleteDependencies, }, }, { @@ -177,8 +185,9 @@ func TestParseDotnetPortableExecutable(t *testing.T) { "ProductVersion": "80.1.7.92", }, expectedPackage: pkg.Package{ - Name: "Better version", - Version: "80.1.7.92", + Name: "Better version", + Version: "80.1.7.92", + Dependencies: pkg.IncompleteDependencies, }, }, { @@ -189,8 +198,9 @@ func TestParseDotnetPortableExecutable(t *testing.T) { "ProductVersion": "80.1.7", }, expectedPackage: pkg.Package{ - Name: "Better version", - Version: "80.1.7.92", + Name: "Better version", + Version: "80.1.7.92", + Dependencies: pkg.IncompleteDependencies, }, }, { @@ -201,8 +211,9 @@ func TestParseDotnetPortableExecutable(t *testing.T) { "ProductVersion": "3.0.1+b86b61bf676163639795b163d8d753b20aad6207", }, expectedPackage: pkg.Package{ - Name: "Higher semantic version Product Version", - Version: "3.0.1+b86b61bf676163639795b163d8d753b20aad6207", + Name: "Higher semantic version Product Version", + Version: "3.0.1+b86b61bf676163639795b163d8d753b20aad6207", + Dependencies: pkg.IncompleteDependencies, }, }, { @@ -213,8 +224,9 @@ func TestParseDotnetPortableExecutable(t *testing.T) { "ProductVersion": "3.0.0", }, expectedPackage: pkg.Package{ - Name: "Higher semantic version File Version", - Version: "3.0.1+b86b61bf676163639795b163d8d753b20aad6207", + Name: "Higher semantic version File Version", + Version: "3.0.1+b86b61bf676163639795b163d8d753b20aad6207", + Dependencies: pkg.IncompleteDependencies, }, }, { @@ -225,8 +237,9 @@ func TestParseDotnetPortableExecutable(t *testing.T) { "ProductVersion": "3.0.1+b86b61bf676163639795b163d8d753b20aad6207", }, expectedPackage: pkg.Package{ - Name: "Invalid semantic version File Version", - Version: "3.0.1+b86b61bf676163639795b163d8d753b20aad6207", + Name: "Invalid semantic version File Version", + Version: "3.0.1+b86b61bf676163639795b163d8d753b20aad6207", + Dependencies: pkg.IncompleteDependencies, }, }, { @@ -237,8 +250,9 @@ func TestParseDotnetPortableExecutable(t *testing.T) { "ProductVersion": "3.0.1+b86b61bf676163639795b163d8d753b20aad6207", }, expectedPackage: pkg.Package{ - Name: "Invalid semantic version File Version", - Version: "3.0.1+b86b61bf676163639795b163d8d753b20aad6207", + Name: "Invalid semantic version File Version", + Version: "3.0.1+b86b61bf676163639795b163d8d753b20aad6207", + Dependencies: pkg.IncompleteDependencies, }, }, { @@ -249,8 +263,9 @@ func TestParseDotnetPortableExecutable(t *testing.T) { "ProductVersion": "A", }, expectedPackage: pkg.Package{ - Name: "Invalid semantic version Product Version", - Version: "3.0.1+b86b61bf676163639795b163d8d753b20aad6207", + Name: "Invalid semantic version Product Version", + Version: "3.0.1+b86b61bf676163639795b163d8d753b20aad6207", + Dependencies: pkg.IncompleteDependencies, }, }, { @@ -261,8 +276,9 @@ func TestParseDotnetPortableExecutable(t *testing.T) { "ProductVersion": "3.0.0", }, expectedPackage: pkg.Package{ - Name: "Semantically equal falls through, chooses File Version with more components", - Version: "3.0.0.0", + Name: "Semantically equal falls through, chooses File Version with more components", + Version: "3.0.0.0", + Dependencies: pkg.IncompleteDependencies, }, }, } @@ -273,7 +289,7 @@ func TestParseDotnetPortableExecutable(t *testing.T) { f := file.LocationReadCloser{ Location: location, } - got, err := buildDotNetPackage(tc.versionResources, f) + got, err := buildDotNetPEPackage(tc.versionResources, f) assert.NoErrorf(t, err, "failed to build package from version resources: %+v", tc.versionResources) // ignore certain metadata diff --git a/syft/pkg/cataloger/elixir/package.go b/syft/pkg/cataloger/elixir/package.go index 50cd3f28f..e87b42337 100644 --- a/syft/pkg/cataloger/elixir/package.go +++ b/syft/pkg/cataloger/elixir/package.go @@ -14,7 +14,9 @@ func newPackage(d pkg.ElixirMixLockEntry, locations ...file.Location) pkg.Packag Locations: file.NewLocationSet(locations...), PURL: packageURL(d), Type: pkg.HexPkg, - Metadata: d, + // we do not attempt to parse dependencies from the mix.lock file + Dependencies: pkg.IncompleteDependencies, + Metadata: d, } p.SetID() diff --git a/syft/pkg/cataloger/elixir/parse_mix_lock_test.go b/syft/pkg/cataloger/elixir/parse_mix_lock_test.go index a8e09e257..8302b4d8b 100644 --- a/syft/pkg/cataloger/elixir/parse_mix_lock_test.go +++ b/syft/pkg/cataloger/elixir/parse_mix_lock_test.go @@ -13,12 +13,13 @@ func TestParseMixLock(t *testing.T) { locations := file.NewLocationSet(file.NewLocation("test-fixtures/mix.lock")) expected := []pkg.Package{ { - Name: "castore", - Version: "0.1.17", - Language: pkg.Elixir, - Type: pkg.HexPkg, - Locations: locations, - PURL: "pkg:hex/castore@0.1.17", + Name: "castore", + Version: "0.1.17", + Language: pkg.Elixir, + Type: pkg.HexPkg, + Locations: locations, + PURL: "pkg:hex/castore@0.1.17", + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.ElixirMixLockEntry{ Name: "castore", Version: "0.1.17", @@ -27,12 +28,13 @@ func TestParseMixLock(t *testing.T) { }, }, { - Name: "connection", - Version: "1.1.0", - Language: pkg.Elixir, - Type: pkg.HexPkg, - Locations: locations, - PURL: "pkg:hex/connection@1.1.0", + Name: "connection", + Version: "1.1.0", + Language: pkg.Elixir, + Type: pkg.HexPkg, + Locations: locations, + PURL: "pkg:hex/connection@1.1.0", + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.ElixirMixLockEntry{ Name: "connection", Version: "1.1.0", @@ -41,12 +43,13 @@ func TestParseMixLock(t *testing.T) { }, }, { - Name: "cowboy", - Version: "2.9.0", - Language: pkg.Elixir, - Type: pkg.HexPkg, - Locations: locations, - PURL: "pkg:hex/cowboy@2.9.0", + Name: "cowboy", + Version: "2.9.0", + Language: pkg.Elixir, + Type: pkg.HexPkg, + Locations: locations, + PURL: "pkg:hex/cowboy@2.9.0", + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.ElixirMixLockEntry{ Name: "cowboy", Version: "2.9.0", @@ -55,12 +58,13 @@ func TestParseMixLock(t *testing.T) { }, }, { - Name: "cowboy_telemetry", - Version: "0.4.0", - Language: pkg.Elixir, - Type: pkg.HexPkg, - Locations: locations, - PURL: "pkg:hex/cowboy_telemetry@0.4.0", + Name: "cowboy_telemetry", + Version: "0.4.0", + Language: pkg.Elixir, + Type: pkg.HexPkg, + Locations: locations, + PURL: "pkg:hex/cowboy_telemetry@0.4.0", + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.ElixirMixLockEntry{ Name: "cowboy_telemetry", Version: "0.4.0", @@ -69,12 +73,13 @@ func TestParseMixLock(t *testing.T) { }, }, { - Name: "cowlib", - Version: "2.11.0", - Language: pkg.Elixir, - Type: pkg.HexPkg, - Locations: locations, - PURL: "pkg:hex/cowlib@2.11.0", + Name: "cowlib", + Version: "2.11.0", + Language: pkg.Elixir, + Type: pkg.HexPkg, + Locations: locations, + PURL: "pkg:hex/cowlib@2.11.0", + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.ElixirMixLockEntry{ Name: "cowlib", Version: "2.11.0", @@ -83,12 +88,13 @@ func TestParseMixLock(t *testing.T) { }, }, { - Name: "db_connection", - Version: "2.4.2", - Language: pkg.Elixir, - Type: pkg.HexPkg, - Locations: locations, - PURL: "pkg:hex/db_connection@2.4.2", + Name: "db_connection", + Version: "2.4.2", + Language: pkg.Elixir, + Type: pkg.HexPkg, + Locations: locations, + PURL: "pkg:hex/db_connection@2.4.2", + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.ElixirMixLockEntry{ Name: "db_connection", Version: "2.4.2", @@ -97,12 +103,13 @@ func TestParseMixLock(t *testing.T) { }, }, { - Name: "decimal", - Version: "2.0.0", - Language: pkg.Elixir, - Type: pkg.HexPkg, - Locations: locations, - PURL: "pkg:hex/decimal@2.0.0", + Name: "decimal", + Version: "2.0.0", + Language: pkg.Elixir, + Type: pkg.HexPkg, + Locations: locations, + PURL: "pkg:hex/decimal@2.0.0", + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.ElixirMixLockEntry{ Name: "decimal", Version: "2.0.0", @@ -111,12 +118,13 @@ func TestParseMixLock(t *testing.T) { }, }, { - Name: "earmark_parser", - Version: "1.4.25", - Language: pkg.Elixir, - Type: pkg.HexPkg, - Locations: locations, - PURL: "pkg:hex/earmark_parser@1.4.25", + Name: "earmark_parser", + Version: "1.4.25", + Language: pkg.Elixir, + Type: pkg.HexPkg, + Locations: locations, + PURL: "pkg:hex/earmark_parser@1.4.25", + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.ElixirMixLockEntry{ Name: "earmark_parser", Version: "1.4.25", @@ -125,12 +133,13 @@ func TestParseMixLock(t *testing.T) { }, }, { - Name: "ecto", - Version: "3.8.1", - Language: pkg.Elixir, - Type: pkg.HexPkg, - Locations: locations, - PURL: "pkg:hex/ecto@3.8.1", + Name: "ecto", + Version: "3.8.1", + Language: pkg.Elixir, + Type: pkg.HexPkg, + Locations: locations, + PURL: "pkg:hex/ecto@3.8.1", + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.ElixirMixLockEntry{ Name: "ecto", Version: "3.8.1", @@ -139,12 +148,13 @@ func TestParseMixLock(t *testing.T) { }, }, { - Name: "ecto_sql", - Version: "3.8.1", - Language: pkg.Elixir, - Type: pkg.HexPkg, - Locations: locations, - PURL: "pkg:hex/ecto_sql@3.8.1", + Name: "ecto_sql", + Version: "3.8.1", + Language: pkg.Elixir, + Type: pkg.HexPkg, + Locations: locations, + PURL: "pkg:hex/ecto_sql@3.8.1", + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.ElixirMixLockEntry{ Name: "ecto_sql", Version: "3.8.1", @@ -153,12 +163,13 @@ func TestParseMixLock(t *testing.T) { }, }, { - Name: "esbuild", - Version: "0.5.0", - Language: pkg.Elixir, - Type: pkg.HexPkg, - Locations: locations, - PURL: "pkg:hex/esbuild@0.5.0", + Name: "esbuild", + Version: "0.5.0", + Language: pkg.Elixir, + Type: pkg.HexPkg, + Locations: locations, + PURL: "pkg:hex/esbuild@0.5.0", + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.ElixirMixLockEntry{ Name: "esbuild", Version: "0.5.0", @@ -167,12 +178,13 @@ func TestParseMixLock(t *testing.T) { }, }, { - Name: "ex_doc", - Version: "0.28.4", - Language: pkg.Elixir, - Type: pkg.HexPkg, - Locations: locations, - PURL: "pkg:hex/ex_doc@0.28.4", + Name: "ex_doc", + Version: "0.28.4", + Language: pkg.Elixir, + Type: pkg.HexPkg, + Locations: locations, + PURL: "pkg:hex/ex_doc@0.28.4", + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.ElixirMixLockEntry{ Name: "ex_doc", Version: "0.28.4", @@ -181,12 +193,13 @@ func TestParseMixLock(t *testing.T) { }, }, { - Name: "gettext", - Version: "0.19.1", - Language: pkg.Elixir, - Type: pkg.HexPkg, - Locations: locations, - PURL: "pkg:hex/gettext@0.19.1", + Name: "gettext", + Version: "0.19.1", + Language: pkg.Elixir, + Type: pkg.HexPkg, + Locations: locations, + PURL: "pkg:hex/gettext@0.19.1", + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.ElixirMixLockEntry{ Name: "gettext", Version: "0.19.1", @@ -195,12 +208,13 @@ func TestParseMixLock(t *testing.T) { }, }, { - Name: "hpax", - Version: "0.1.1", - Language: pkg.Elixir, - Type: pkg.HexPkg, - Locations: locations, - PURL: "pkg:hex/hpax@0.1.1", + Name: "hpax", + Version: "0.1.1", + Language: pkg.Elixir, + Type: pkg.HexPkg, + Locations: locations, + PURL: "pkg:hex/hpax@0.1.1", + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.ElixirMixLockEntry{ Name: "hpax", Version: "0.1.1", @@ -209,12 +223,13 @@ func TestParseMixLock(t *testing.T) { }, }, { - Name: "jason", - Version: "1.3.0", - Language: pkg.Elixir, - Type: pkg.HexPkg, - Locations: locations, - PURL: "pkg:hex/jason@1.3.0", + Name: "jason", + Version: "1.3.0", + Language: pkg.Elixir, + Type: pkg.HexPkg, + Locations: locations, + PURL: "pkg:hex/jason@1.3.0", + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.ElixirMixLockEntry{ Name: "jason", Version: "1.3.0", diff --git a/syft/pkg/cataloger/erlang/package.go b/syft/pkg/cataloger/erlang/package.go index 60157996c..7723d6ebb 100644 --- a/syft/pkg/cataloger/erlang/package.go +++ b/syft/pkg/cataloger/erlang/package.go @@ -14,7 +14,9 @@ func newPackageFromRebar(d pkg.ErlangRebarLockEntry, locations ...file.Location) Locations: file.NewLocationSet(locations...), PURL: packageURLFromRebar(d), Type: pkg.HexPkg, - Metadata: d, + // we do not attempt to parse dependencies from the rebar.lock file + Dependencies: pkg.IncompleteDependencies, + Metadata: d, } p.SetID() @@ -42,7 +44,9 @@ func newPackageFromOTP(name, version string, locations ...file.Location) pkg.Pac Language: pkg.Erlang, Locations: file.NewLocationSet(locations...), PURL: packageURLFromOTP(name, version), - Type: pkg.ErlangOTPPkg, + // we do not attempt to parse dependencies from app files + Dependencies: pkg.IncompleteDependencies, + Type: pkg.ErlangOTPPkg, } p.SetID() diff --git a/syft/pkg/cataloger/erlang/parse_otp_app_test.go b/syft/pkg/cataloger/erlang/parse_otp_app_test.go index 93c0aa238..0f911cb48 100644 --- a/syft/pkg/cataloger/erlang/parse_otp_app_test.go +++ b/syft/pkg/cataloger/erlang/parse_otp_app_test.go @@ -18,11 +18,12 @@ func TestParseOTPApplication(t *testing.T) { fixture: "test-fixtures/rabbitmq.app", expected: []pkg.Package{ { - Name: "rabbit", - Version: "3.12.10", - Language: pkg.Erlang, - Type: pkg.ErlangOTPPkg, - PURL: "pkg:otp/rabbit@3.12.10", + Name: "rabbit", + Version: "3.12.10", + Language: pkg.Erlang, + Type: pkg.ErlangOTPPkg, + PURL: "pkg:otp/rabbit@3.12.10", + Dependencies: pkg.IncompleteDependencies, }, }, }, diff --git a/syft/pkg/cataloger/erlang/parse_rebar_lock_test.go b/syft/pkg/cataloger/erlang/parse_rebar_lock_test.go index 67e309cd3..9a02bd4b4 100644 --- a/syft/pkg/cataloger/erlang/parse_rebar_lock_test.go +++ b/syft/pkg/cataloger/erlang/parse_rebar_lock_test.go @@ -18,11 +18,12 @@ func TestParseRebarLock(t *testing.T) { fixture: "test-fixtures/rebar.lock", expected: []pkg.Package{ { - Name: "certifi", - Version: "2.9.0", - Language: pkg.Erlang, - Type: pkg.HexPkg, - PURL: "pkg:hex/certifi@2.9.0", + Name: "certifi", + Version: "2.9.0", + Language: pkg.Erlang, + Type: pkg.HexPkg, + PURL: "pkg:hex/certifi@2.9.0", + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.ErlangRebarLockEntry{ Name: "certifi", Version: "2.9.0", @@ -31,11 +32,12 @@ func TestParseRebarLock(t *testing.T) { }, }, { - Name: "idna", - Version: "6.1.1", - Language: pkg.Erlang, - Type: pkg.HexPkg, - PURL: "pkg:hex/idna@6.1.1", + Name: "idna", + Version: "6.1.1", + Language: pkg.Erlang, + Type: pkg.HexPkg, + PURL: "pkg:hex/idna@6.1.1", + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.ErlangRebarLockEntry{ Name: "idna", Version: "6.1.1", @@ -44,11 +46,12 @@ func TestParseRebarLock(t *testing.T) { }, }, { - Name: "metrics", - Version: "1.0.1", - Language: pkg.Erlang, - Type: pkg.HexPkg, - PURL: "pkg:hex/metrics@1.0.1", + Name: "metrics", + Version: "1.0.1", + Language: pkg.Erlang, + Type: pkg.HexPkg, + PURL: "pkg:hex/metrics@1.0.1", + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.ErlangRebarLockEntry{ Name: "metrics", Version: "1.0.1", @@ -57,11 +60,12 @@ func TestParseRebarLock(t *testing.T) { }, }, { - Name: "mimerl", - Version: "1.2.0", - Language: pkg.Erlang, - Type: pkg.HexPkg, - PURL: "pkg:hex/mimerl@1.2.0", + Name: "mimerl", + Version: "1.2.0", + Language: pkg.Erlang, + Type: pkg.HexPkg, + PURL: "pkg:hex/mimerl@1.2.0", + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.ErlangRebarLockEntry{ Name: "mimerl", Version: "1.2.0", @@ -70,11 +74,12 @@ func TestParseRebarLock(t *testing.T) { }, }, { - Name: "parse_trans", - Version: "3.3.1", - Language: pkg.Erlang, - Type: pkg.HexPkg, - PURL: "pkg:hex/parse_trans@3.3.1", + Name: "parse_trans", + Version: "3.3.1", + Language: pkg.Erlang, + Type: pkg.HexPkg, + PURL: "pkg:hex/parse_trans@3.3.1", + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.ErlangRebarLockEntry{ Name: "parse_trans", Version: "3.3.1", @@ -83,11 +88,12 @@ func TestParseRebarLock(t *testing.T) { }, }, { - Name: "ssl_verify_fun", - Version: "1.1.6", - Language: pkg.Erlang, - Type: pkg.HexPkg, - PURL: "pkg:hex/ssl_verify_fun@1.1.6", + Name: "ssl_verify_fun", + Version: "1.1.6", + Language: pkg.Erlang, + Type: pkg.HexPkg, + PURL: "pkg:hex/ssl_verify_fun@1.1.6", + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.ErlangRebarLockEntry{ Name: "ssl_verify_fun", Version: "1.1.6", @@ -96,11 +102,12 @@ func TestParseRebarLock(t *testing.T) { }, }, { - Name: "unicode_util_compat", - Version: "0.7.0", - Language: pkg.Erlang, - Type: pkg.HexPkg, - PURL: "pkg:hex/unicode_util_compat@0.7.0", + Name: "unicode_util_compat", + Version: "0.7.0", + Language: pkg.Erlang, + Type: pkg.HexPkg, + PURL: "pkg:hex/unicode_util_compat@0.7.0", + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.ErlangRebarLockEntry{ Name: "unicode_util_compat", Version: "0.7.0", @@ -117,11 +124,12 @@ func TestParseRebarLock(t *testing.T) { // {<<"bcrypt">>, <<"A6763BD4E1AF46D34776F85B7995E63A02978DE110C077E9570ED17006E03386">>}, // {<<"bcrypt">>, <<"3418821BC17CE6E96A4A77D1A88D7485BF783E212069FACFC79510AFBFF95352">>}, { - Name: "bcrypt", - Version: "1.1.5", - Language: pkg.Erlang, - Type: pkg.HexPkg, - PURL: "pkg:hex/bcrypt@1.1.5", + Name: "bcrypt", + Version: "1.1.5", + Language: pkg.Erlang, + Type: pkg.HexPkg, + PURL: "pkg:hex/bcrypt@1.1.5", + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.ErlangRebarLockEntry{ Name: "bcrypt", Version: "1.1.5", @@ -134,11 +142,12 @@ func TestParseRebarLock(t *testing.T) { // {ref,"14308ab927cfa69324742c3de720578094e0bb19"}}, // 1}, { - Name: "bson", - Version: "14308ab927cfa69324742c3de720578094e0bb19", - Language: pkg.Erlang, - Type: pkg.HexPkg, - PURL: "pkg:hex/bson@14308ab927cfa69324742c3de720578094e0bb19", + Name: "bson", + Version: "14308ab927cfa69324742c3de720578094e0bb19", + Language: pkg.Erlang, + Type: pkg.HexPkg, + PURL: "pkg:hex/bson@14308ab927cfa69324742c3de720578094e0bb19", + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.ErlangRebarLockEntry{ Name: "bson", Version: "14308ab927cfa69324742c3de720578094e0bb19", @@ -148,11 +157,12 @@ func TestParseRebarLock(t *testing.T) { // {<<"certifi">>, <<"6F2A475689DD47F19FB74334859D460A2DC4E3252A3324BD2111B8F0429E7E21">>}, {<<"stdout_formatter">>, <<"EC24868D8619757A68F0798357C7190807A1CFC42CE90C18C23760E59249A21A">>}, // {<<"certifi">>, <<"266DA46BDB06D6C6D35FDE799BCB28D36D985D424AD7C08B5BB48F5B5CDD4641">>}, { - Name: "certifi", - Version: "2.9.0", - Language: pkg.Erlang, - Type: pkg.HexPkg, - PURL: "pkg:hex/certifi@2.9.0", + Name: "certifi", + Version: "2.9.0", + Language: pkg.Erlang, + Type: pkg.HexPkg, + PURL: "pkg:hex/certifi@2.9.0", + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.ErlangRebarLockEntry{ Name: "certifi", Version: "2.9.0", @@ -164,11 +174,12 @@ func TestParseRebarLock(t *testing.T) { // {<<"stdout_formatter">>, <<"EC24868D8619757A68F0798357C7190807A1CFC42CE90C18C23760E59249A21A">>}, // {<<"stdout_formatter">>, <<"6B9CAAD8930006F9BB35680C5D3311917AC67690C3AF1BA018623324C015ABE5">>}, { - Name: "stdout_formatter", - Version: "0.2.3", - Language: pkg.Erlang, - Type: pkg.HexPkg, - PURL: "pkg:hex/stdout_formatter@0.2.3", + Name: "stdout_formatter", + Version: "0.2.3", + Language: pkg.Erlang, + Type: pkg.HexPkg, + PURL: "pkg:hex/stdout_formatter@0.2.3", + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.ErlangRebarLockEntry{ Name: "stdout_formatter", Version: "0.2.3", @@ -181,11 +192,12 @@ func TestParseRebarLock(t *testing.T) { // {ref,"4835239dca5a5f4ac7202dd94d7effcaa617d575"}}, // 0}, { - Name: "swc", - Version: "4835239dca5a5f4ac7202dd94d7effcaa617d575", - Language: pkg.Erlang, - Type: pkg.HexPkg, - PURL: "pkg:hex/swc@4835239dca5a5f4ac7202dd94d7effcaa617d575", + Name: "swc", + Version: "4835239dca5a5f4ac7202dd94d7effcaa617d575", + Language: pkg.Erlang, + Type: pkg.HexPkg, + PURL: "pkg:hex/swc@4835239dca5a5f4ac7202dd94d7effcaa617d575", + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.ErlangRebarLockEntry{ Name: "swc", Version: "4835239dca5a5f4ac7202dd94d7effcaa617d575", @@ -195,11 +207,12 @@ func TestParseRebarLock(t *testing.T) { // {<<"syslog">>, <<"6419A232BEA84F07B56DC575225007FFE34D9FDC91ABE6F1B2F254FD71D8EFC2">>}, // {<<"syslog">>, <<"4C6A41373C7E20587BE33EF841D3DE6F3BEBA08519809329ECC4D27B15B659E1">>}, { - Name: "syslog", - Version: "1.1.0", - Language: pkg.Erlang, - Type: pkg.HexPkg, - PURL: "pkg:hex/syslog@1.1.0", + Name: "syslog", + Version: "1.1.0", + Language: pkg.Erlang, + Type: pkg.HexPkg, + PURL: "pkg:hex/syslog@1.1.0", + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.ErlangRebarLockEntry{ Name: "syslog", Version: "1.1.0", @@ -211,11 +224,12 @@ func TestParseRebarLock(t *testing.T) { // {<<"unicode_util_compat">>, <<"BC84380C9AB48177092F43AC89E4DFA2C6D62B40B8BD132B1059ECC7232F9A78">>}]}, // {<<"unicode_util_compat">>, <<"25EEE6D67DF61960CF6A794239566599B09E17E668D3700247BC498638152521">>}]} { - Name: "unicode_util_compat", - Version: "0.7.0", - Language: pkg.Erlang, - Type: pkg.HexPkg, - PURL: "pkg:hex/unicode_util_compat@0.7.0", + Name: "unicode_util_compat", + Version: "0.7.0", + Language: pkg.Erlang, + Type: pkg.HexPkg, + PURL: "pkg:hex/unicode_util_compat@0.7.0", + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.ErlangRebarLockEntry{ Name: "unicode_util_compat", Version: "0.7.0", @@ -228,11 +242,12 @@ func TestParseRebarLock(t *testing.T) { // {ref,"6d622aa8c901ae7777433aef2bd049e380c474a6"}}, // 0}]}. { - Name: "vernemq_dev", - Version: "6d622aa8c901ae7777433aef2bd049e380c474a6", - Language: pkg.Erlang, - Type: pkg.HexPkg, - PURL: "pkg:hex/vernemq_dev@6d622aa8c901ae7777433aef2bd049e380c474a6", + Name: "vernemq_dev", + Version: "6d622aa8c901ae7777433aef2bd049e380c474a6", + Language: pkg.Erlang, + Type: pkg.HexPkg, + PURL: "pkg:hex/vernemq_dev@6d622aa8c901ae7777433aef2bd049e380c474a6", + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.ErlangRebarLockEntry{ Name: "vernemq_dev", Version: "6d622aa8c901ae7777433aef2bd049e380c474a6", diff --git a/syft/pkg/cataloger/gentoo/cataloger_test.go b/syft/pkg/cataloger/gentoo/cataloger_test.go index 6fb80e780..235bf0286 100644 --- a/syft/pkg/cataloger/gentoo/cataloger_test.go +++ b/syft/pkg/cataloger/gentoo/cataloger_test.go @@ -22,8 +22,9 @@ func TestPortageCataloger(t *testing.T) { file.NewLocation("var/db/pkg/app-containers/skopeo-1.5.1/SIZE"), expectedLicenseLocation, ), - Licenses: pkg.NewLicenseSet(pkg.NewLicensesFromLocation(expectedLicenseLocation, "Apache-2.0", "BSD", "BSD-2", "CC-BY-SA-4.0", "ISC", "MIT")...), - Type: pkg.PortagePkg, + Licenses: pkg.NewLicenseSet(pkg.NewLicensesFromLocation(expectedLicenseLocation, "Apache-2.0", "BSD", "BSD-2", "CC-BY-SA-4.0", "ISC", "MIT")...), + Type: pkg.PortagePkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.PortageEntry{ InstalledSize: 27937835, Files: []pkg.PortageFileRecord{ diff --git a/syft/pkg/cataloger/gentoo/parse_portage_contents.go b/syft/pkg/cataloger/gentoo/parse_portage_contents.go index 56370d012..5c8cbdee1 100644 --- a/syft/pkg/cataloger/gentoo/parse_portage_contents.go +++ b/syft/pkg/cataloger/gentoo/parse_portage_contents.go @@ -45,7 +45,8 @@ func parsePortageContents(_ context.Context, resolver file.Resolver, _ *generic. Locations: file.NewLocationSet( reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), - Type: pkg.PortagePkg, + Dependencies: pkg.IncompleteDependencies, + Type: pkg.PortagePkg, Metadata: pkg.PortageEntry{ // ensure the default value for a collection is never nil since this may be shown as JSON Files: make([]pkg.PortageFileRecord, 0), diff --git a/syft/pkg/cataloger/githubactions/package.go b/syft/pkg/cataloger/githubactions/package.go index ff1567a91..9700571c0 100644 --- a/syft/pkg/cataloger/githubactions/package.go +++ b/syft/pkg/cataloger/githubactions/package.go @@ -31,7 +31,9 @@ func newGithubActionWorkflowPackageUsage(name, version string, workflowLocation Version: version, Locations: file.NewLocationSet(workflowLocation.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), PURL: packageURL(name, version), - Type: pkg.GithubActionWorkflowPkg, + // we have full visibility into the dependencies of a workflow file except for when using shared workflows + Dependencies: pkg.CompleteDependencies, + Type: pkg.GithubActionWorkflowPkg, } p.SetID() @@ -45,7 +47,9 @@ func newGithubActionPackageUsage(name, version string, workflowLocation file.Loc Version: version, Locations: file.NewLocationSet(workflowLocation.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), PURL: packageURL(name, version), - Type: pkg.GithubActionPkg, + // we cannot see what the dependencies are for a github action are locally from workflow yaml files + Dependencies: pkg.IncompleteDependencies, + Type: pkg.GithubActionPkg, } p.SetID() diff --git a/syft/pkg/cataloger/githubactions/parse_composite_action_test.go b/syft/pkg/cataloger/githubactions/parse_composite_action_test.go index 080d80816..18622d4c8 100644 --- a/syft/pkg/cataloger/githubactions/parse_composite_action_test.go +++ b/syft/pkg/cataloger/githubactions/parse_composite_action_test.go @@ -15,18 +15,20 @@ func Test_parseCompositeActionForActionUsage(t *testing.T) { expected := []pkg.Package{ { - Name: "actions/setup-go", - Version: "v4", - Type: pkg.GithubActionPkg, - Locations: fixtureLocationSet, - PURL: "pkg:github/actions/setup-go@v4", + Name: "actions/setup-go", + Version: "v4", + Type: pkg.GithubActionPkg, + Locations: fixtureLocationSet, + PURL: "pkg:github/actions/setup-go@v4", + Dependencies: pkg.IncompleteDependencies, }, { - Name: "actions/cache", - Version: "v3", - Type: pkg.GithubActionPkg, - Locations: fixtureLocationSet, - PURL: "pkg:github/actions/cache@v3", + Name: "actions/cache", + Version: "v3", + Type: pkg.GithubActionPkg, + Locations: fixtureLocationSet, + PURL: "pkg:github/actions/cache@v3", + Dependencies: pkg.IncompleteDependencies, }, } diff --git a/syft/pkg/cataloger/githubactions/parse_workflow_test.go b/syft/pkg/cataloger/githubactions/parse_workflow_test.go index 52c4e1ebd..e8eeecf54 100644 --- a/syft/pkg/cataloger/githubactions/parse_workflow_test.go +++ b/syft/pkg/cataloger/githubactions/parse_workflow_test.go @@ -15,39 +15,44 @@ func Test_parseWorkflowForActionUsage(t *testing.T) { expected := []pkg.Package{ { - Name: "./.github/actions/bootstrap", - Version: "", - Type: pkg.GithubActionPkg, - Locations: fixtureLocationSet, - PURL: "", // don't have enough context without parsing the git origin, which still may not be accurate + Name: "./.github/actions/bootstrap", + Version: "", + Type: pkg.GithubActionPkg, + Locations: fixtureLocationSet, + PURL: "", // don't have enough context without parsing the git origin, which still may not be accurate + Dependencies: pkg.IncompleteDependencies, }, { - Name: "actions/cache", - Version: "v3", - Type: pkg.GithubActionPkg, - Locations: fixtureLocationSet, - PURL: "pkg:github/actions/cache@v3", + Name: "actions/cache", + Version: "v3", + Type: pkg.GithubActionPkg, + Locations: fixtureLocationSet, + PURL: "pkg:github/actions/cache@v3", + Dependencies: pkg.IncompleteDependencies, }, { - Name: "actions/cache/restore", - Version: "v3", - Type: pkg.GithubActionPkg, - Locations: fixtureLocationSet, - PURL: "pkg:github/actions/cache@v3#restore", + Name: "actions/cache/restore", + Version: "v3", + Type: pkg.GithubActionPkg, + Locations: fixtureLocationSet, + PURL: "pkg:github/actions/cache@v3#restore", + Dependencies: pkg.IncompleteDependencies, }, { - Name: "actions/cache/save", - Version: "v3", - Type: pkg.GithubActionPkg, - Locations: fixtureLocationSet, - PURL: "pkg:github/actions/cache@v3#save", + Name: "actions/cache/save", + Version: "v3", + Type: pkg.GithubActionPkg, + Locations: fixtureLocationSet, + PURL: "pkg:github/actions/cache@v3#save", + Dependencies: pkg.IncompleteDependencies, }, { - Name: "actions/checkout", - Version: "v4", - Type: pkg.GithubActionPkg, - Locations: fixtureLocationSet, - PURL: "pkg:github/actions/checkout@v4", + Name: "actions/checkout", + Version: "v4", + Type: pkg.GithubActionPkg, + Locations: fixtureLocationSet, + PURL: "pkg:github/actions/checkout@v4", + Dependencies: pkg.IncompleteDependencies, }, } @@ -61,25 +66,28 @@ func Test_parseWorkflowForWorkflowUsage(t *testing.T) { expected := []pkg.Package{ { - Name: "octo-org/this-repo/.github/workflows/workflow-1.yml", - Version: "172239021f7ba04fe7327647b213799853a9eb89", - Type: pkg.GithubActionWorkflowPkg, - Locations: fixtureLocationSet, - PURL: "pkg:github/octo-org/this-repo@172239021f7ba04fe7327647b213799853a9eb89#.github/workflows/workflow-1.yml", + Name: "octo-org/this-repo/.github/workflows/workflow-1.yml", + Version: "172239021f7ba04fe7327647b213799853a9eb89", + Type: pkg.GithubActionWorkflowPkg, + Locations: fixtureLocationSet, + PURL: "pkg:github/octo-org/this-repo@172239021f7ba04fe7327647b213799853a9eb89#.github/workflows/workflow-1.yml", + Dependencies: pkg.CompleteDependencies, }, { - Name: "./.github/workflows/workflow-2.yml", - Version: "", - Type: pkg.GithubActionWorkflowPkg, - Locations: fixtureLocationSet, - PURL: "", // don't have enough context without parsing the git origin, which still may not be accurate + Name: "./.github/workflows/workflow-2.yml", + Version: "", + Type: pkg.GithubActionWorkflowPkg, + Locations: fixtureLocationSet, + PURL: "", // don't have enough context without parsing the git origin, which still may not be accurate + Dependencies: pkg.CompleteDependencies, }, { - Name: "octo-org/another-repo/.github/workflows/workflow.yml", - Version: "v1", - Type: pkg.GithubActionWorkflowPkg, - Locations: fixtureLocationSet, - PURL: "pkg:github/octo-org/another-repo@v1#.github/workflows/workflow.yml", + Name: "octo-org/another-repo/.github/workflows/workflow.yml", + Version: "v1", + Type: pkg.GithubActionWorkflowPkg, + Locations: fixtureLocationSet, + PURL: "pkg:github/octo-org/another-repo@v1#.github/workflows/workflow.yml", + Dependencies: pkg.CompleteDependencies, }, } diff --git a/syft/pkg/cataloger/golang/package.go b/syft/pkg/cataloger/golang/package.go index c3071420c..70be97454 100644 --- a/syft/pkg/cataloger/golang/package.go +++ b/syft/pkg/cataloger/golang/package.go @@ -22,6 +22,9 @@ func (c *goBinaryCataloger) newGoBinaryPackage(dep *debug.Module, mainModule, go Language: pkg.Go, Type: pkg.GoModulePkg, Locations: file.NewLocationSet(locations...), + // we don't have a way to express on a package or relationship the nature of "//indirect" markings on dependencies + // so though the dependencies are complete and separable with the raw data, the data in the SBOM is not separable. + Dependencies: pkg.MixedDependencies, Metadata: pkg.GolangBinaryBuildinfoEntry{ GoCompiledVersion: goVersion, H1Digest: dep.Sum, diff --git a/syft/pkg/cataloger/golang/parse_go_binary_test.go b/syft/pkg/cataloger/golang/parse_go_binary_test.go index 565fda090..924950520 100644 --- a/syft/pkg/cataloger/golang/parse_go_binary_test.go +++ b/syft/pkg/cataloger/golang/parse_go_binary_test.go @@ -161,6 +161,7 @@ func TestBuildGoPkgInfo(t *testing.T) { }, ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), + Dependencies: pkg.MixedDependencies, Metadata: pkg.GolangBinaryBuildinfoEntry{ GoCompiledVersion: goCompiledVersion, Architecture: archDetails, @@ -208,7 +209,8 @@ func TestBuildGoPkgInfo(t *testing.T) { }, ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), - Metadata: pkg.GolangBinaryBuildinfoEntry{}, + Dependencies: pkg.MixedDependencies, + Metadata: pkg.GolangBinaryBuildinfoEntry{}, }, }, }, @@ -253,6 +255,7 @@ func TestBuildGoPkgInfo(t *testing.T) { }, ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), + Dependencies: pkg.MixedDependencies, Metadata: pkg.GolangBinaryBuildinfoEntry{ GoCompiledVersion: goCompiledVersion, Architecture: archDetails, @@ -291,6 +294,7 @@ func TestBuildGoPkgInfo(t *testing.T) { }, ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), + Dependencies: pkg.MixedDependencies, Metadata: pkg.GolangBinaryBuildinfoEntry{ GoCompiledVersion: goCompiledVersion, Architecture: archDetails, @@ -365,6 +369,7 @@ func TestBuildGoPkgInfo(t *testing.T) { }, ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), + Dependencies: pkg.MixedDependencies, Metadata: pkg.GolangBinaryBuildinfoEntry{ GoCompiledVersion: goCompiledVersion, Architecture: archDetails, @@ -432,6 +437,7 @@ func TestBuildGoPkgInfo(t *testing.T) { }, ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), + Dependencies: pkg.MixedDependencies, Metadata: pkg.GolangBinaryBuildinfoEntry{ GoCompiledVersion: goCompiledVersion, Architecture: archDetails, @@ -497,6 +503,7 @@ func TestBuildGoPkgInfo(t *testing.T) { }, ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), + Dependencies: pkg.MixedDependencies, Metadata: pkg.GolangBinaryBuildinfoEntry{ GoCompiledVersion: goCompiledVersion, Architecture: archDetails, @@ -554,6 +561,7 @@ func TestBuildGoPkgInfo(t *testing.T) { }, ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), + Dependencies: pkg.MixedDependencies, Metadata: pkg.GolangBinaryBuildinfoEntry{ GoCompiledVersion: goCompiledVersion, Architecture: archDetails, @@ -611,6 +619,7 @@ func TestBuildGoPkgInfo(t *testing.T) { }, ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), + Dependencies: pkg.MixedDependencies, Metadata: pkg.GolangBinaryBuildinfoEntry{ GoCompiledVersion: goCompiledVersion, Architecture: archDetails, @@ -669,6 +678,7 @@ func TestBuildGoPkgInfo(t *testing.T) { }, ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), + Dependencies: pkg.MixedDependencies, Metadata: pkg.GolangBinaryBuildinfoEntry{ GoCompiledVersion: goCompiledVersion, Architecture: archDetails, @@ -741,6 +751,7 @@ func TestBuildGoPkgInfo(t *testing.T) { }, ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), + Dependencies: pkg.MixedDependencies, Metadata: pkg.GolangBinaryBuildinfoEntry{ GoCompiledVersion: goCompiledVersion, Architecture: archDetails, @@ -762,6 +773,7 @@ func TestBuildGoPkgInfo(t *testing.T) { }, ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), + Dependencies: pkg.MixedDependencies, Metadata: pkg.GolangBinaryBuildinfoEntry{ GoCompiledVersion: goCompiledVersion, Architecture: archDetails, @@ -819,12 +831,14 @@ func TestBuildGoPkgInfo(t *testing.T) { }, ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), + Dependencies: pkg.MixedDependencies, Metadata: pkg.GolangBinaryBuildinfoEntry{ GoCompiledVersion: goCompiledVersion, Architecture: archDetails, H1Digest: "h1:PjhxBct4MZii8FFR8+oeS7QOvxKOTZXgk63EU2XpfJE=", MainModule: "github.com/anchore/syft", - }}, + }, + }, { Name: "golang.org/x/term", Version: "v0.0.0-20210916214954-140adaaadfaf", @@ -839,6 +853,7 @@ func TestBuildGoPkgInfo(t *testing.T) { }, ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), + Dependencies: pkg.MixedDependencies, Metadata: pkg.GolangBinaryBuildinfoEntry{ GoCompiledVersion: goCompiledVersion, Architecture: archDetails, @@ -882,6 +897,7 @@ func TestBuildGoPkgInfo(t *testing.T) { }, ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), + Dependencies: pkg.MixedDependencies, Metadata: pkg.GolangBinaryBuildinfoEntry{ GoCompiledVersion: goCompiledVersion, Architecture: archDetails, @@ -941,6 +957,7 @@ func TestBuildGoPkgInfo(t *testing.T) { }, ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), + Dependencies: pkg.MixedDependencies, Metadata: pkg.GolangBinaryBuildinfoEntry{ GoCompiledVersion: "go1.22.2", Architecture: archDetails, @@ -993,6 +1010,7 @@ func TestBuildGoPkgInfo(t *testing.T) { }, ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), + Dependencies: pkg.MixedDependencies, Metadata: pkg.GolangBinaryBuildinfoEntry{ GoCompiledVersion: "go1.22.2", Architecture: archDetails, @@ -1013,6 +1031,7 @@ func TestBuildGoPkgInfo(t *testing.T) { }, ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), + Dependencies: pkg.MixedDependencies, Metadata: pkg.GolangBinaryBuildinfoEntry{ GoCompiledVersion: "go1.22.2", BuildSettings: []pkg.KeyValue{ diff --git a/syft/pkg/cataloger/golang/parse_go_mod.go b/syft/pkg/cataloger/golang/parse_go_mod.go index cfb373e90..14786c94b 100644 --- a/syft/pkg/cataloger/golang/parse_go_mod.go +++ b/syft/pkg/cataloger/golang/parse_go_mod.go @@ -66,6 +66,9 @@ func (c *goModCataloger) parseGoModFile(ctx context.Context, resolver file.Resol PURL: packageURL(m.Mod.Path, m.Mod.Version), Language: pkg.Go, Type: pkg.GoModulePkg, + // we don't have a way to express on a package or relationship the nature of "//indirect" markings on dependencies + // so though the dependencies are complete and separable with the raw data, the data in the SBOM is not separable. + Dependencies: pkg.MixedDependencies, Metadata: pkg.GolangModuleEntry{ H1Digest: digests[fmt.Sprintf("%s %s", m.Mod.Path, m.Mod.Version)], }, @@ -91,6 +94,9 @@ func (c *goModCataloger) parseGoModFile(ctx context.Context, resolver file.Resol PURL: packageURL(m.New.Path, m.New.Version), Language: pkg.Go, Type: pkg.GoModulePkg, + // we don't have a way to express on a package or relationship the nature of "//indirect" markings on dependencies + // so though the dependencies are complete and separable with the raw data, the data in the SBOM is not separable. + Dependencies: pkg.MixedDependencies, Metadata: pkg.GolangModuleEntry{ H1Digest: digests[fmt.Sprintf("%s %s", m.New.Path, m.New.Version)], }, diff --git a/syft/pkg/cataloger/golang/parse_go_mod_test.go b/syft/pkg/cataloger/golang/parse_go_mod_test.go index 20538e4c7..3c699b8a0 100644 --- a/syft/pkg/cataloger/golang/parse_go_mod_test.go +++ b/syft/pkg/cataloger/golang/parse_go_mod_test.go @@ -18,13 +18,14 @@ func TestParseGoMod(t *testing.T) { fixture: "test-fixtures/one-package", expected: []pkg.Package{ { - Name: "github.com/bmatcuk/doublestar", - Version: "v1.3.1", - PURL: "pkg:golang/github.com/bmatcuk/doublestar@v1.3.1", - Locations: file.NewLocationSet(file.NewLocation("test-fixtures/one-package")), - Language: pkg.Go, - Type: pkg.GoModulePkg, - Metadata: pkg.GolangModuleEntry{}, + Name: "github.com/bmatcuk/doublestar", + Version: "v1.3.1", + PURL: "pkg:golang/github.com/bmatcuk/doublestar@v1.3.1", + Locations: file.NewLocationSet(file.NewLocation("test-fixtures/one-package")), + Language: pkg.Go, + Type: pkg.GoModulePkg, + Dependencies: pkg.MixedDependencies, + Metadata: pkg.GolangModuleEntry{}, }, }, }, @@ -33,58 +34,64 @@ func TestParseGoMod(t *testing.T) { fixture: "test-fixtures/many-packages", expected: []pkg.Package{ { - Name: "github.com/anchore/archiver/v3", - Version: "v3.5.2", - PURL: "pkg:golang/github.com/anchore/archiver@v3.5.2#v3", - Locations: file.NewLocationSet(file.NewLocation("test-fixtures/many-packages")), - Language: pkg.Go, - Type: pkg.GoModulePkg, - Metadata: pkg.GolangModuleEntry{}, + Name: "github.com/anchore/archiver/v3", + Version: "v3.5.2", + PURL: "pkg:golang/github.com/anchore/archiver@v3.5.2#v3", + Locations: file.NewLocationSet(file.NewLocation("test-fixtures/many-packages")), + Language: pkg.Go, + Type: pkg.GoModulePkg, + Dependencies: pkg.MixedDependencies, + Metadata: pkg.GolangModuleEntry{}, }, { - Name: "github.com/anchore/go-testutils", - Version: "v0.0.0-20200624184116-66aa578126db", - PURL: "pkg:golang/github.com/anchore/go-testutils@v0.0.0-20200624184116-66aa578126db", - Locations: file.NewLocationSet(file.NewLocation("test-fixtures/many-packages")), - Language: pkg.Go, - Type: pkg.GoModulePkg, - Metadata: pkg.GolangModuleEntry{}, + Name: "github.com/anchore/go-testutils", + Version: "v0.0.0-20200624184116-66aa578126db", + PURL: "pkg:golang/github.com/anchore/go-testutils@v0.0.0-20200624184116-66aa578126db", + Locations: file.NewLocationSet(file.NewLocation("test-fixtures/many-packages")), + Language: pkg.Go, + Type: pkg.GoModulePkg, + Dependencies: pkg.MixedDependencies, + Metadata: pkg.GolangModuleEntry{}, }, { - Name: "github.com/anchore/go-version", - Version: "v1.2.2-0.20200701162849-18adb9c92b9b", - PURL: "pkg:golang/github.com/anchore/go-version@v1.2.2-0.20200701162849-18adb9c92b9b", - Locations: file.NewLocationSet(file.NewLocation("test-fixtures/many-packages")), - Language: pkg.Go, - Type: pkg.GoModulePkg, - Metadata: pkg.GolangModuleEntry{}, + Name: "github.com/anchore/go-version", + Version: "v1.2.2-0.20200701162849-18adb9c92b9b", + PURL: "pkg:golang/github.com/anchore/go-version@v1.2.2-0.20200701162849-18adb9c92b9b", + Locations: file.NewLocationSet(file.NewLocation("test-fixtures/many-packages")), + Language: pkg.Go, + Type: pkg.GoModulePkg, + Dependencies: pkg.MixedDependencies, + Metadata: pkg.GolangModuleEntry{}, }, { - Name: "github.com/anchore/stereoscope", - Version: "v0.0.0-20200706164556-7cf39d7f4639", - PURL: "pkg:golang/github.com/anchore/stereoscope@v0.0.0-20200706164556-7cf39d7f4639", - Locations: file.NewLocationSet(file.NewLocation("test-fixtures/many-packages")), - Language: pkg.Go, - Type: pkg.GoModulePkg, - Metadata: pkg.GolangModuleEntry{}, + Name: "github.com/anchore/stereoscope", + Version: "v0.0.0-20200706164556-7cf39d7f4639", + PURL: "pkg:golang/github.com/anchore/stereoscope@v0.0.0-20200706164556-7cf39d7f4639", + Locations: file.NewLocationSet(file.NewLocation("test-fixtures/many-packages")), + Language: pkg.Go, + Type: pkg.GoModulePkg, + Dependencies: pkg.MixedDependencies, + Metadata: pkg.GolangModuleEntry{}, }, { - Name: "github.com/bmatcuk/doublestar", - Version: "v8.8.8", - PURL: "pkg:golang/github.com/bmatcuk/doublestar@v8.8.8", - Locations: file.NewLocationSet(file.NewLocation("test-fixtures/many-packages")), - Language: pkg.Go, - Type: pkg.GoModulePkg, - Metadata: pkg.GolangModuleEntry{}, + Name: "github.com/bmatcuk/doublestar", + Version: "v8.8.8", + PURL: "pkg:golang/github.com/bmatcuk/doublestar@v8.8.8", + Locations: file.NewLocationSet(file.NewLocation("test-fixtures/many-packages")), + Language: pkg.Go, + Type: pkg.GoModulePkg, + Dependencies: pkg.MixedDependencies, + Metadata: pkg.GolangModuleEntry{}, }, { - Name: "github.com/go-test/deep", - Version: "v1.0.6", - PURL: "pkg:golang/github.com/go-test/deep@v1.0.6", - Locations: file.NewLocationSet(file.NewLocation("test-fixtures/many-packages")), - Language: pkg.Go, - Type: pkg.GoModulePkg, - Metadata: pkg.GolangModuleEntry{}, + Name: "github.com/go-test/deep", + Version: "v1.0.6", + PURL: "pkg:golang/github.com/go-test/deep@v1.0.6", + Locations: file.NewLocationSet(file.NewLocation("test-fixtures/many-packages")), + Language: pkg.Go, + Type: pkg.GoModulePkg, + Dependencies: pkg.MixedDependencies, + Metadata: pkg.GolangModuleEntry{}, }, }, }, @@ -111,35 +118,38 @@ func Test_GoSumHashes(t *testing.T) { fixture: "test-fixtures/go-sum-hashes", expected: []pkg.Package{ { - Name: "github.com/CycloneDX/cyclonedx-go", - Version: "v0.6.0", - PURL: "pkg:golang/github.com/CycloneDX/cyclonedx-go@v0.6.0", - Locations: file.NewLocationSet(file.NewLocation("go.mod")), - FoundBy: "go-module-file-cataloger", - Language: pkg.Go, - Type: pkg.GoModulePkg, - Metadata: pkg.GolangModuleEntry{}, + Name: "github.com/CycloneDX/cyclonedx-go", + Version: "v0.6.0", + PURL: "pkg:golang/github.com/CycloneDX/cyclonedx-go@v0.6.0", + Locations: file.NewLocationSet(file.NewLocation("go.mod")), + FoundBy: "go-module-file-cataloger", + Language: pkg.Go, + Type: pkg.GoModulePkg, + Dependencies: pkg.MixedDependencies, + Metadata: pkg.GolangModuleEntry{}, }, { - Name: "github.com/acarl005/stripansi", - Version: "v0.0.0-20180116102854-5a71ef0e047d", - PURL: "pkg:golang/github.com/acarl005/stripansi@v0.0.0-20180116102854-5a71ef0e047d", - Locations: file.NewLocationSet(file.NewLocation("go.mod")), - FoundBy: "go-module-file-cataloger", - Language: pkg.Go, - Type: pkg.GoModulePkg, + Name: "github.com/acarl005/stripansi", + Version: "v0.0.0-20180116102854-5a71ef0e047d", + PURL: "pkg:golang/github.com/acarl005/stripansi@v0.0.0-20180116102854-5a71ef0e047d", + Locations: file.NewLocationSet(file.NewLocation("go.mod")), + FoundBy: "go-module-file-cataloger", + Language: pkg.Go, + Type: pkg.GoModulePkg, + Dependencies: pkg.MixedDependencies, Metadata: pkg.GolangModuleEntry{ H1Digest: "h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8=", }, }, { - Name: "github.com/mgutz/ansi", - Version: "v0.0.0-20200706080929-d51e80ef957d", - PURL: "pkg:golang/github.com/mgutz/ansi@v0.0.0-20200706080929-d51e80ef957d", - Locations: file.NewLocationSet(file.NewLocation("go.mod")), - FoundBy: "go-module-file-cataloger", - Language: pkg.Go, - Type: pkg.GoModulePkg, + Name: "github.com/mgutz/ansi", + Version: "v0.0.0-20200706080929-d51e80ef957d", + PURL: "pkg:golang/github.com/mgutz/ansi@v0.0.0-20200706080929-d51e80ef957d", + Locations: file.NewLocationSet(file.NewLocation("go.mod")), + FoundBy: "go-module-file-cataloger", + Language: pkg.Go, + Type: pkg.GoModulePkg, + Dependencies: pkg.MixedDependencies, Metadata: pkg.GolangModuleEntry{ H1Digest: "h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI=", }, diff --git a/syft/pkg/cataloger/haskell/package.go b/syft/pkg/cataloger/haskell/package.go index 6594ce216..ec0dfb0eb 100644 --- a/syft/pkg/cataloger/haskell/package.go +++ b/syft/pkg/cataloger/haskell/package.go @@ -14,7 +14,9 @@ func newPackage(name, version string, m any, location file.Location) pkg.Package PURL: packageURL(name, version), Language: pkg.Haskell, Type: pkg.HackagePkg, - Metadata: m, + // in all cases (cabal, stack, etc.) we do not attempt to glean dependency information + Dependencies: pkg.IncompleteDependencies, + Metadata: m, } p.SetID() diff --git a/syft/pkg/cataloger/haskell/parse_cabal_freeze_test.go b/syft/pkg/cataloger/haskell/parse_cabal_freeze_test.go index acb58b74e..57ac1a480 100644 --- a/syft/pkg/cataloger/haskell/parse_cabal_freeze_test.go +++ b/syft/pkg/cataloger/haskell/parse_cabal_freeze_test.go @@ -15,92 +15,103 @@ func TestParseCabalFreeze(t *testing.T) { expectedPkgs := []pkg.Package{ { - Name: "Cabal", - Version: "3.2.1.0", - PURL: "pkg:hackage/Cabal@3.2.1.0", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "Cabal", + Version: "3.2.1.0", + PURL: "pkg:hackage/Cabal@3.2.1.0", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.IncompleteDependencies, }, { - Name: "Diff", - Version: "0.4.1", - PURL: "pkg:hackage/Diff@0.4.1", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "Diff", + Version: "0.4.1", + PURL: "pkg:hackage/Diff@0.4.1", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.IncompleteDependencies, }, { - Name: "HTTP", - Version: "4000.3.16", - PURL: "pkg:hackage/HTTP@4000.3.16", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "HTTP", + Version: "4000.3.16", + PURL: "pkg:hackage/HTTP@4000.3.16", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.IncompleteDependencies, }, { - Name: "HUnit", - Version: "1.6.2.0", - PURL: "pkg:hackage/HUnit@1.6.2.0", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "HUnit", + Version: "1.6.2.0", + PURL: "pkg:hackage/HUnit@1.6.2.0", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.IncompleteDependencies, }, { - Name: "OneTuple", - Version: "0.3.1", - PURL: "pkg:hackage/OneTuple@0.3.1", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "OneTuple", + Version: "0.3.1", + PURL: "pkg:hackage/OneTuple@0.3.1", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.IncompleteDependencies, }, { - Name: "Only", - Version: "0.1", - PURL: "pkg:hackage/Only@0.1", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "Only", + Version: "0.1", + PURL: "pkg:hackage/Only@0.1", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.IncompleteDependencies, }, { - Name: "PyF", - Version: "0.10.2.0", - PURL: "pkg:hackage/PyF@0.10.2.0", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "PyF", + Version: "0.10.2.0", + PURL: "pkg:hackage/PyF@0.10.2.0", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.IncompleteDependencies, }, { - Name: "QuickCheck", - Version: "2.14.2", - PURL: "pkg:hackage/QuickCheck@2.14.2", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "QuickCheck", + Version: "2.14.2", + PURL: "pkg:hackage/QuickCheck@2.14.2", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.IncompleteDependencies, }, { - Name: "RSA", - Version: "2.4.1", - PURL: "pkg:hackage/RSA@2.4.1", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "RSA", + Version: "2.4.1", + PURL: "pkg:hackage/RSA@2.4.1", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.IncompleteDependencies, }, { - Name: "SHA", - Version: "1.6.4.4", - PURL: "pkg:hackage/SHA@1.6.4.4", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "SHA", + Version: "1.6.4.4", + PURL: "pkg:hackage/SHA@1.6.4.4", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.IncompleteDependencies, }, { - Name: "Spock", - Version: "0.14.0.0", - PURL: "pkg:hackage/Spock@0.14.0.0", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "Spock", + Version: "0.14.0.0", + PURL: "pkg:hackage/Spock@0.14.0.0", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.IncompleteDependencies, }, } diff --git a/syft/pkg/cataloger/haskell/parse_stack_lock_test.go b/syft/pkg/cataloger/haskell/parse_stack_lock_test.go index ee84ae092..b465553b9 100644 --- a/syft/pkg/cataloger/haskell/parse_stack_lock_test.go +++ b/syft/pkg/cataloger/haskell/parse_stack_lock_test.go @@ -16,108 +16,117 @@ func TestParseStackLock(t *testing.T) { expectedPkgs := []pkg.Package{ { - Name: "HTTP", - Version: "4000.3.16", - PURL: "pkg:hackage/HTTP@4000.3.16", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "HTTP", + Version: "4000.3.16", + PURL: "pkg:hackage/HTTP@4000.3.16", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.HackageStackYamlLockEntry{ PkgHash: "6042643c15a0b43e522a6693f1e322f05000d519543a84149cb80aeffee34f71", SnapshotURL: url, }, }, { - Name: "configurator-pg", - Version: "0.2.6", - PURL: "pkg:hackage/configurator-pg@0.2.6", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "configurator-pg", + Version: "0.2.6", + PURL: "pkg:hackage/configurator-pg@0.2.6", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.HackageStackYamlLockEntry{ PkgHash: "cd9b06a458428e493a4d6def725af7ab1ab0fef678fbd871f9586fc7f9aa70be", SnapshotURL: url, }, }, { - Name: "hasql-dynamic-statements", - Version: "0.3.1.1", - PURL: "pkg:hackage/hasql-dynamic-statements@0.3.1.1", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "hasql-dynamic-statements", + Version: "0.3.1.1", + PURL: "pkg:hackage/hasql-dynamic-statements@0.3.1.1", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.HackageStackYamlLockEntry{ PkgHash: "2cfe6e75990e690f595a87cbe553f2e90fcd738610f6c66749c81cc4396b2cc4", SnapshotURL: url, }, }, { - Name: "hasql-implicits", - Version: "0.1.0.4", - PURL: "pkg:hackage/hasql-implicits@0.1.0.4", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "hasql-implicits", + Version: "0.1.0.4", + PURL: "pkg:hackage/hasql-implicits@0.1.0.4", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.HackageStackYamlLockEntry{ PkgHash: "0848d3cbc9d94e1e539948fa0be4d0326b26335034161bf8076785293444ca6f", SnapshotURL: url, }, }, { - Name: "hasql-pool", - Version: "0.5.2.2", - PURL: "pkg:hackage/hasql-pool@0.5.2.2", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "hasql-pool", + Version: "0.5.2.2", + PURL: "pkg:hackage/hasql-pool@0.5.2.2", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.HackageStackYamlLockEntry{ PkgHash: "b56d4dea112d97a2ef4b2749508c0ca646828cb2d77b827e8dc433d249bb2062", SnapshotURL: url, }, }, { - Name: "lens-aeson", - Version: "1.1.3", - PURL: "pkg:hackage/lens-aeson@1.1.3", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "lens-aeson", + Version: "1.1.3", + PURL: "pkg:hackage/lens-aeson@1.1.3", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.HackageStackYamlLockEntry{ PkgHash: "52c8eaecd2d1c2a969c0762277c4a8ee72c339a686727d5785932e72ef9c3050", SnapshotURL: url, }, }, { - Name: "optparse-applicative", - Version: "0.16.1.0", - PURL: "pkg:hackage/optparse-applicative@0.16.1.0", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "optparse-applicative", + Version: "0.16.1.0", + PURL: "pkg:hackage/optparse-applicative@0.16.1.0", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.HackageStackYamlLockEntry{ PkgHash: "418c22ed6a19124d457d96bc66bd22c93ac22fad0c7100fe4972bbb4ac989731", SnapshotURL: url, }, }, { - Name: "protolude", - Version: "0.3.2", - PURL: "pkg:hackage/protolude@0.3.2", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "protolude", + Version: "0.3.2", + PURL: "pkg:hackage/protolude@0.3.2", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.HackageStackYamlLockEntry{ PkgHash: "2a38b3dad40d238ab644e234b692c8911423f9d3ed0e36b62287c4a698d92cd1", SnapshotURL: url, }, }, { - Name: "ptr", - Version: "0.16.8.2", - PURL: "pkg:hackage/ptr@0.16.8.2", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "ptr", + Version: "0.16.8.2", + PURL: "pkg:hackage/ptr@0.16.8.2", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.HackageStackYamlLockEntry{ PkgHash: "708ebb95117f2872d2c5a554eb6804cf1126e86abe793b2673f913f14e5eb1ac", SnapshotURL: url, diff --git a/syft/pkg/cataloger/haskell/parse_stack_yaml_test.go b/syft/pkg/cataloger/haskell/parse_stack_yaml_test.go index ee4586396..04040bd83 100644 --- a/syft/pkg/cataloger/haskell/parse_stack_yaml_test.go +++ b/syft/pkg/cataloger/haskell/parse_stack_yaml_test.go @@ -15,89 +15,97 @@ func TestParseStackYaml(t *testing.T) { expectedPkgs := []pkg.Package{ { - Name: "ShellCheck", - Version: "0.8.0", - PURL: "pkg:hackage/ShellCheck@0.8.0", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "ShellCheck", + Version: "0.8.0", + PURL: "pkg:hackage/ShellCheck@0.8.0", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.HackageStackYamlEntry{ PkgHash: "353c9322847b661e4c6f7c83c2acf8e5c08b682fbe516c7d46c29605937543df", }, }, { - Name: "colourista", - Version: "0.1.0.1", - PURL: "pkg:hackage/colourista@0.1.0.1", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "colourista", + Version: "0.1.0.1", + PURL: "pkg:hackage/colourista@0.1.0.1", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.HackageStackYamlEntry{ PkgHash: "98353ee0e2f5d97d2148513f084c1cd37dfda03e48aa9dd7a017c9d9c0ba710e", }, }, { - Name: "language-docker", - Version: "11.0.0", - PURL: "pkg:hackage/language-docker@11.0.0", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "language-docker", + Version: "11.0.0", + PURL: "pkg:hackage/language-docker@11.0.0", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.HackageStackYamlEntry{ PkgHash: "3406ff0c1d592490f53ead8cf2cd22bdf3d79fd125ccaf3add683f6d71c24d55", }, }, { - Name: "spdx", - Version: "1.0.0.2", - PURL: "pkg:hackage/spdx@1.0.0.2", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "spdx", + Version: "1.0.0.2", + PURL: "pkg:hackage/spdx@1.0.0.2", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.HackageStackYamlEntry{ PkgHash: "7dfac9b454ff2da0abb7560f0ffbe00ae442dd5cb76e8be469f77e6988a70fed", }, }, { - Name: "hspec", - Version: "2.9.4", - PURL: "pkg:hackage/hspec@2.9.4", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "hspec", + Version: "2.9.4", + PURL: "pkg:hackage/hspec@2.9.4", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.HackageStackYamlEntry{ PkgHash: "658a6a74d5a70c040edd6df2a12228c6d9e63082adaad1ed4d0438ad082a0ef3", }, }, { - Name: "hspec-core", - Version: "2.9.4", - PURL: "pkg:hackage/hspec-core@2.9.4", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "hspec-core", + Version: "2.9.4", + PURL: "pkg:hackage/hspec-core@2.9.4", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.HackageStackYamlEntry{ PkgHash: "a126e9087409fef8dcafcd2f8656456527ac7bb163ed4d9cb3a57589042a5fe8", }, }, { - Name: "hspec-discover", - Version: "2.9.4", - PURL: "pkg:hackage/hspec-discover@2.9.4", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "hspec-discover", + Version: "2.9.4", + PURL: "pkg:hackage/hspec-discover@2.9.4", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.HackageStackYamlEntry{ PkgHash: "fbcf49ecfc3d4da53e797fd0275264cba776ffa324ee223e2a3f4ec2d2c9c4a6", }, }, { - Name: "stm", - Version: "2.5.0.2", - PURL: "pkg:hackage/stm@2.5.0.2", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "stm", + Version: "2.5.0.2", + PURL: "pkg:hackage/stm@2.5.0.2", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.HackageStackYamlEntry{ PkgHash: "e4dc6473faaa75fbd7eccab4e3ee1d651d75bb0e49946ef0b8b751ccde771a55", }, diff --git a/syft/pkg/cataloger/internal/pkgtest/test_generic_parser.go b/syft/pkg/cataloger/internal/pkgtest/test_generic_parser.go index 96bd79450..4041de280 100644 --- a/syft/pkg/cataloger/internal/pkgtest/test_generic_parser.go +++ b/syft/pkg/cataloger/internal/pkgtest/test_generic_parser.go @@ -44,6 +44,7 @@ type CatalogTester struct { licenseComparer cmptest.LicenseComparer packageStringer func(pkg.Package) string customAssertions []func(t *testing.T, pkgs []pkg.Package, relationships []artifact.Relationship) + ctx context.Context } func NewCatalogTester() *CatalogTester { @@ -106,6 +107,11 @@ func (p *CatalogTester) WithLinuxRelease(r linux.Release) *CatalogTester { return p } +func (p *CatalogTester) WithContext(ctx context.Context) *CatalogTester { + p.ctx = ctx + return p +} + func (p *CatalogTester) WithEnv(env *generic.Environment) *CatalogTester { p.env = env return p @@ -236,7 +242,14 @@ func (p *CatalogTester) TestCataloger(t *testing.T, cataloger pkg.Cataloger) { resolver := NewObservingResolver(p.resolver) - pkgs, relationships, err := cataloger.Catalog(context.Background(), resolver) + var ctx context.Context + if p.ctx != nil { + ctx = p.ctx + } else { + ctx = context.Background() + } + + pkgs, relationships, err := cataloger.Catalog(ctx, resolver) // this is a minimum set, the resolver may return more that just this list for _, path := range p.expectedPathResponses { diff --git a/syft/pkg/cataloger/java/archive_parser_test.go b/syft/pkg/cataloger/java/archive_parser_test.go index b1779bbf1..cf243994d 100644 --- a/syft/pkg/cataloger/java/archive_parser_test.go +++ b/syft/pkg/cataloger/java/archive_parser_test.go @@ -437,6 +437,7 @@ func TestParseJar(t *testing.T) { } func TestParseNestedJar(t *testing.T) { + ctx := licenses.SetContextLicenseScanner(context.Background(), licenses.TestingOnlyScanner()) tests := []struct { fixture string expected []pkg.Package @@ -638,7 +639,7 @@ func TestParseNestedJar(t *testing.T) { require.NoError(t, err) gap := newGenericArchiveParserAdapter(ArchiveCatalogerConfig{}) - actual, _, err := gap.processJavaArchive(context.Background(), file.LocationReadCloser{ + actual, _, err := gap.processJavaArchive(ctx, file.LocationReadCloser{ Location: file.NewLocation(fixture.Name()), ReadCloser: fixture, }, nil) @@ -1166,6 +1167,8 @@ func Test_parseJavaArchive_regressions(t *testing.T) { }, } + ctx := licenses.SetContextLicenseScanner(context.Background(), licenses.TestingOnlyScanner()) + tests := []struct { name string fixtureName string @@ -1355,6 +1358,7 @@ func Test_parseJavaArchive_regressions(t *testing.T) { pkgtest.NewCatalogTester(). FromFile(t, generateJavaMetadataJarFixture(t, tt.fixtureName, tt.fileExtension)). Expects(tt.expectedPkgs, tt.expectedRelationships). + WithContext(ctx). WithCompareOptions( cmpopts.IgnoreFields(pkg.JavaArchive{}, "ArchiveDigests"), cmp.Comparer(func(x, y pkg.KeyValue) bool { diff --git a/syft/pkg/cataloger/java/cataloger_test.go b/syft/pkg/cataloger/java/cataloger_test.go index 9df9825df..fe227dae0 100644 --- a/syft/pkg/cataloger/java/cataloger_test.go +++ b/syft/pkg/cataloger/java/cataloger_test.go @@ -1,8 +1,10 @@ package java import ( + "context" "testing" + "github.com/anchore/syft/internal/licenses" "github.com/anchore/syft/syft/cataloging" "github.com/anchore/syft/syft/cpe" "github.com/anchore/syft/syft/file" @@ -11,6 +13,8 @@ import ( ) func Test_ArchiveCataloger_Globs(t *testing.T) { + ctx := licenses.SetContextLicenseScanner(context.Background(), licenses.TestingOnlyScanner()) + tests := []struct { name string fixture string @@ -59,6 +63,7 @@ func Test_ArchiveCataloger_Globs(t *testing.T) { pkgtest.NewCatalogTester(). FromDirectory(t, test.fixture). ExpectsResolverContentQueries(test.expected). + WithContext(ctx). TestCataloger(t, NewArchiveCataloger( ArchiveCatalogerConfig{ @@ -128,7 +133,8 @@ func TestJvmDistributionCataloger(t *testing.T) { cpe.Must("cpe:2.3:a:oracle:jre:1.8.0:update411:*:*:*:*:*:*", cpe.DeclaredSource), cpe.Must("cpe:2.3:a:oracle:jdk:1.8.0:update411:*:*:*:*:*:*", cpe.DeclaredSource), }, - PURL: "pkg:generic/oracle/jdk@1.8.0_411-b25", + PURL: "pkg:generic/oracle/jdk@1.8.0_411-b25", + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.JavaVMInstallation{ Release: pkg.JavaVMRelease{ JavaRuntimeVersion: "1.8.0_411-b25", @@ -150,14 +156,15 @@ func TestJvmDistributionCataloger(t *testing.T) { name: "valid post-jep223", fixture: "test-fixtures/jvm-installs/valid-post-jep223", expected: pkg.Package{ - Name: "openjdk", - Version: "21.0.4+7-LTS", - FoundBy: "java-jvm-cataloger", - Locations: file.NewLocationSet(file.NewLocation("jvm/openjdk/release")), - Licenses: pkg.NewLicenseSet(), - Type: pkg.BinaryPkg, - CPEs: []cpe.CPE{cpe.Must("cpe:2.3:a:oracle:openjdk:21.0.4:*:*:*:*:*:*:*", cpe.DeclaredSource)}, - PURL: "pkg:generic/oracle/openjdk@21.0.4%2B7-LTS?repository_url=https://github.com/adoptium/jdk21u.git", + Name: "openjdk", + Version: "21.0.4+7-LTS", + FoundBy: "java-jvm-cataloger", + Locations: file.NewLocationSet(file.NewLocation("jvm/openjdk/release")), + Licenses: pkg.NewLicenseSet(), + Type: pkg.BinaryPkg, + CPEs: []cpe.CPE{cpe.Must("cpe:2.3:a:oracle:openjdk:21.0.4:*:*:*:*:*:*:*", cpe.DeclaredSource)}, + PURL: "pkg:generic/oracle/openjdk@21.0.4%2B7-LTS?repository_url=https://github.com/adoptium/jdk21u.git", + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.JavaVMInstallation{ Release: pkg.JavaVMRelease{ Implementor: "Eclipse Adoptium", diff --git a/syft/pkg/cataloger/java/parse_gradle_lockfile.go b/syft/pkg/cataloger/java/parse_gradle_lockfile.go index a2aa11b5d..d354b094b 100644 --- a/syft/pkg/cataloger/java/parse_gradle_lockfile.go +++ b/syft/pkg/cataloger/java/parse_gradle_lockfile.go @@ -23,17 +23,17 @@ type lockfileDependency struct { func parseGradleLockfile(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { var pkgs []pkg.Package - // Create a new scanner to read the file + // create a new scanner to read the file scanner := bufio.NewScanner(reader) - // Create slices to hold the dependencies and plugins + // create slices to hold the dependencies and plugins dependencies := []lockfileDependency{} - // Loop over all lines in the file + // loop over all lines in the file for scanner.Scan() { line := scanner.Text() - // Trim leading and trailing whitespace from the line + // trim leading and trailing whitespace from the line line = strings.TrimSpace(line) groupNameVersion := line @@ -42,7 +42,7 @@ func parseGradleLockfile(_ context.Context, _ file.Resolver, _ *generic.Environm // we have a version directly specified if len(parts) == 3 { - // Create a new Dependency struct and add it to the dependencies slice + // create a new Dependency struct and add it to the dependencies slice dep := lockfileDependency{Group: parts[0], Name: parts[1], Version: parts[2]} dependencies = append(dependencies, dep) } @@ -68,7 +68,9 @@ func parseGradleLockfile(_ context.Context, _ file.Resolver, _ *generic.Environm Language: pkg.Java, Type: pkg.JavaPkg, PURL: packageURL(dep.Name, dep.Version, archive), - Metadata: archive, + // though we do have dependencies listed, we do not have them related to one another, thus we must answer incomplete + Dependencies: pkg.IncompleteDependencies, + Metadata: archive, } mappedPkg.SetID() pkgs = append(pkgs, mappedPkg) diff --git a/syft/pkg/cataloger/java/parse_gradle_lockfile_test.go b/syft/pkg/cataloger/java/parse_gradle_lockfile_test.go index 3208d937d..878df65c3 100644 --- a/syft/pkg/cataloger/java/parse_gradle_lockfile_test.go +++ b/syft/pkg/cataloger/java/parse_gradle_lockfile_test.go @@ -17,41 +17,45 @@ func Test_parserGradleLockfile(t *testing.T) { input: "test-fixtures/gradle/gradle.lockfile", expected: []pkg.Package{ { - Name: "commons-text", - Version: "1.8", - Language: pkg.Java, - Type: pkg.JavaPkg, - PURL: "pkg:maven/org.apache.commons/commons-text@1.8", + Name: "commons-text", + Version: "1.8", + Language: pkg.Java, + Type: pkg.JavaPkg, + PURL: "pkg:maven/org.apache.commons/commons-text@1.8", + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.JavaArchive{ PomProject: &pkg.JavaPomProject{GroupID: "org.apache.commons", ArtifactID: "commons-text", Version: "1.8", Name: "commons-text"}, }, }, { - Name: "hamcrest-core", - Version: "1.3", - Language: pkg.Java, - Type: pkg.JavaPkg, - PURL: "pkg:maven/org.hamcrest/hamcrest-core@1.3", + Name: "hamcrest-core", + Version: "1.3", + Language: pkg.Java, + Type: pkg.JavaPkg, + PURL: "pkg:maven/org.hamcrest/hamcrest-core@1.3", + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.JavaArchive{ PomProject: &pkg.JavaPomProject{GroupID: "org.hamcrest", ArtifactID: "hamcrest-core", Version: "1.3", Name: "hamcrest-core"}, }, }, { - Name: "joda-time", - Version: "2.2", - Language: pkg.Java, - Type: pkg.JavaPkg, - PURL: "pkg:maven/joda-time/joda-time@2.2", + Name: "joda-time", + Version: "2.2", + Language: pkg.Java, + Type: pkg.JavaPkg, + PURL: "pkg:maven/joda-time/joda-time@2.2", + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.JavaArchive{ PomProject: &pkg.JavaPomProject{GroupID: "joda-time", ArtifactID: "joda-time", Version: "2.2", Name: "joda-time"}, }, }, { - Name: "junit", - Version: "4.12", - Language: pkg.Java, - Type: pkg.JavaPkg, - PURL: "pkg:maven/junit/junit@4.12", + Name: "junit", + Version: "4.12", + Language: pkg.Java, + Type: pkg.JavaPkg, + PURL: "pkg:maven/junit/junit@4.12", + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.JavaArchive{ PomProject: &pkg.JavaPomProject{GroupID: "junit", ArtifactID: "junit", Version: "4.12", Name: "junit"}, }, diff --git a/syft/pkg/cataloger/java/parse_jvm_release.go b/syft/pkg/cataloger/java/parse_jvm_release.go index e39be4779..cc43e02c4 100644 --- a/syft/pkg/cataloger/java/parse_jvm_release.go +++ b/syft/pkg/cataloger/java/parse_jvm_release.go @@ -98,6 +98,8 @@ func parseJVMRelease(_ context.Context, resolver file.Resolver, _ *generic.Envir PURL: jvmPurl(*ri, version, vendor, product), Licenses: licenses, Type: pkg.BinaryPkg, + // we don't have any dependency information about the JVM package itself + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.JavaVMInstallation{ Release: *ri, Files: files, diff --git a/syft/pkg/cataloger/java/parse_pom_xml.go b/syft/pkg/cataloger/java/parse_pom_xml.go index dc4922774..f49c97eb3 100644 --- a/syft/pkg/cataloger/java/parse_pom_xml.go +++ b/syft/pkg/cataloger/java/parse_pom_xml.go @@ -51,7 +51,7 @@ func (p pomXMLCataloger) Catalog(ctx context.Context, fileResolver file.Resolver r.AddPom(ctx, pom, pomLocation) } - var pkgs []pkg.Package + var pkgs []*pkg.Package var relationships []artifact.Relationship resolved := map[maven.ID]*pkg.Package{} @@ -65,7 +65,7 @@ func (p pomXMLCataloger) Catalog(ctx context.Context, fileResolver file.Resolver continue } resolved[id] = mainPkg - pkgs = append(pkgs, *mainPkg) + pkgs = append(pkgs, mainPkg) } // catalog all dependencies @@ -81,7 +81,27 @@ func (p pomXMLCataloger) Catalog(ctx context.Context, fileResolver file.Resolver errs = unknown.Join(errs, newErrs) } - return pkgs, relationships, errs + return finalizePackages(pkgs), finalizeRelationships(relationships), errs +} + +func finalizeRelationships(relationships []artifact.Relationship) []artifact.Relationship { + for i := range relationships { + if f, ok := relationships[i].From.(*pkg.Package); ok { + relationships[i].From = *f + } + if t, ok := relationships[i].To.(*pkg.Package); ok { + relationships[i].To = *t + } + } + return relationships +} + +func finalizePackages(pkgs []*pkg.Package) []pkg.Package { + var values []pkg.Package + for i := range pkgs { + values = append(values, *pkgs[i]) + } + return values } func readPomFromLocation(fileResolver file.Resolver, pomLocation file.Location) (*maven.Project, error) { @@ -142,7 +162,10 @@ func newPackageFromMavenPom(ctx context.Context, r *maven.Resolver, pom *maven.P Type: pkg.JavaPkg, FoundBy: pomCatalogerName, PURL: packageURL(id.ArtifactID, id.Version, m), - Metadata: m, + // later in processing we may resolve the dependencies for this package (e.g. online enrichment) + // but at this point there is not enough information to claim we have complete dependency information + Dependencies: pkg.IncompleteDependencies, + Metadata: m, } finalizePackage(p) @@ -150,9 +173,9 @@ func newPackageFromMavenPom(ctx context.Context, r *maven.Resolver, pom *maven.P return p } -func collectDependencies(ctx context.Context, r *maven.Resolver, resolved map[maven.ID]*pkg.Package, parentPkg *pkg.Package, pom *maven.Project, loc file.Location, includeTransitiveDependencies bool) ([]pkg.Package, []artifact.Relationship, error) { +func collectDependencies(ctx context.Context, r *maven.Resolver, resolved map[maven.ID]*pkg.Package, parentPkg *pkg.Package, pom *maven.Project, loc file.Location, includeTransitiveDependencies bool) ([]*pkg.Package, []artifact.Relationship, error) { var errs error - var pkgs []pkg.Package + var pkgs []*pkg.Package var relationships []artifact.Relationship pomID := r.ResolveID(ctx, pom) @@ -196,16 +219,25 @@ func collectDependencies(ctx context.Context, r *maven.Resolver, resolved map[ma } } - pkgs = append(pkgs, *depPkg) + pkgs = append(pkgs, depPkg) if parentPkg != nil { - relationships = append(relationships, artifact.Relationship{ - From: *depPkg, - To: *parentPkg, + relationships = append(relationships, artifact.Relationship{ //nolint:gocritic // we intentionally want to use the reference to the package which will still be mutated and finalized to a value later + // both the to and from packages may be mutated based on the resolved dependencies, so we need references to these values + // to ensure the nodes used are consistent with the final state of the packages. + // note: it is VITAL that these references are replaced with values by the caller of this function before using + // these relationships in the cataloger output. + From: depPkg, + To: parentPkg, Type: artifact.DependencyOfRelationship, }) } } + // as long as we have no errors, we can claim we have complete direct dependencies (even if there are none) + if errs == nil { + parentPkg.Dependencies = pkg.CompleteDependencies + } + return pkgs, relationships, errs } @@ -270,7 +302,10 @@ func newPackageFromDependency(ctx context.Context, r *maven.Resolver, pom *maven Language: pkg.Java, Type: pkg.JavaPkg, // TODO: should we differentiate between packages from jar/war/zip versus packages from a pom.xml that were not installed yet? FoundBy: pomCatalogerName, - Metadata: m, + // later in processing we may resolve the dependencies for this package (e.g. online enrichment) but + // by default we cannot claim we have complete dependency information + Dependencies: pkg.IncompleteDependencies, + Metadata: m, } finalizePackage(p) diff --git a/syft/pkg/cataloger/java/parse_pom_xml_test.go b/syft/pkg/cataloger/java/parse_pom_xml_test.go index 6bd0a5f23..67bf40677 100644 --- a/syft/pkg/cataloger/java/parse_pom_xml_test.go +++ b/syft/pkg/cataloger/java/parse_pom_xml_test.go @@ -24,13 +24,14 @@ func Test_parsePomXML(t *testing.T) { pomLocation := file.NewLocationSet(file.NewLocation("pom.xml")) exampleJavaAppMaven := pkg.Package{ - Name: "example-java-app-maven", - Version: "0.1.0", - PURL: "pkg:maven/org.anchore/example-java-app-maven@0.1.0", - Language: pkg.Java, - Type: pkg.JavaPkg, - FoundBy: pomCatalogerName, - Locations: pomLocation, + Name: "example-java-app-maven", + Version: "0.1.0", + PURL: "pkg:maven/org.anchore/example-java-app-maven@0.1.0", + Language: pkg.Java, + Type: pkg.JavaPkg, + FoundBy: pomCatalogerName, + Locations: pomLocation, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.JavaArchive{ PomProject: &pkg.JavaPomProject{ GroupID: "org.anchore", @@ -42,13 +43,14 @@ func Test_parsePomXML(t *testing.T) { finalizePackage(&exampleJavaAppMaven) jodaTime := pkg.Package{ - Name: "joda-time", - Version: "2.9.2", - PURL: "pkg:maven/com.joda/joda-time@2.9.2", - Language: pkg.Java, - Type: pkg.JavaPkg, - FoundBy: pomCatalogerName, - Locations: pomLocation, + Name: "joda-time", + Version: "2.9.2", + PURL: "pkg:maven/com.joda/joda-time@2.9.2", + Language: pkg.Java, + Type: pkg.JavaPkg, + FoundBy: pomCatalogerName, + Locations: pomLocation, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.JavaArchive{ PomProperties: &pkg.JavaPomProperties{ GroupID: "com.joda", @@ -59,13 +61,14 @@ func Test_parsePomXML(t *testing.T) { finalizePackage(&jodaTime) junit := pkg.Package{ - Name: "junit", - Version: "4.12", - PURL: "pkg:maven/junit/junit@4.12", - Language: pkg.Java, - Type: pkg.JavaPkg, - FoundBy: pomCatalogerName, - Locations: pomLocation, + Name: "junit", + Version: "4.12", + PURL: "pkg:maven/junit/junit@4.12", + Language: pkg.Java, + Type: pkg.JavaPkg, + FoundBy: pomCatalogerName, + Locations: pomLocation, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.JavaArchive{ PomProperties: &pkg.JavaPomProperties{ GroupID: "junit", @@ -472,12 +475,13 @@ func getCommonsTextExpectedPackages(resolved bool) expected { pomXmlLocation := file.NewLocationSet(file.NewLocation("pom.xml")) commonsText := pkg.Package{ - Name: "commons-text", - Version: "1.10.0", - PURL: "pkg:maven/org.apache.commons/commons-text@1.10.0", - Language: pkg.Java, - Type: pkg.JavaPkg, - FoundBy: pomCatalogerName, + Name: "commons-text", + Version: "1.10.0", + PURL: "pkg:maven/org.apache.commons/commons-text@1.10.0", + Language: pkg.Java, + Type: pkg.JavaPkg, + FoundBy: pomCatalogerName, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.JavaArchive{ PomProject: &pkg.JavaPomProject{ Parent: &pkg.JavaPomParent{ @@ -496,12 +500,13 @@ func getCommonsTextExpectedPackages(resolved bool) expected { } commonsLang3 := pkg.Package{ - Name: "commons-lang3", - Version: "3.12.0", - PURL: "pkg:maven/org.apache.commons/commons-lang3@3.12.0", - Language: pkg.Java, - Type: pkg.JavaPkg, - FoundBy: pomCatalogerName, + Name: "commons-lang3", + Version: "3.12.0", + PURL: "pkg:maven/org.apache.commons/commons-lang3@3.12.0", + Language: pkg.Java, + Type: pkg.JavaPkg, + FoundBy: pomCatalogerName, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.JavaArchive{ PomProperties: &pkg.JavaPomProperties{ GroupID: "org.apache.commons", @@ -511,12 +516,13 @@ func getCommonsTextExpectedPackages(resolved bool) expected { } junitJupiter := pkg.Package{ - Name: "junit-jupiter", - Version: "", - PURL: "pkg:maven/org.junit.jupiter/junit-jupiter", - Language: pkg.Java, - Type: pkg.JavaPkg, - FoundBy: pomCatalogerName, + Name: "junit-jupiter", + Version: "", + PURL: "pkg:maven/org.junit.jupiter/junit-jupiter", + Language: pkg.Java, + Type: pkg.JavaPkg, + FoundBy: pomCatalogerName, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.JavaArchive{ PomProperties: &pkg.JavaPomProperties{ GroupID: "org.junit.jupiter", @@ -527,12 +533,13 @@ func getCommonsTextExpectedPackages(resolved bool) expected { } assertjCore := pkg.Package{ - Name: "assertj-core", - Version: "3.23.1", - PURL: "pkg:maven/org.assertj/assertj-core@3.23.1", - Language: pkg.Java, - Type: pkg.JavaPkg, - FoundBy: pomCatalogerName, + Name: "assertj-core", + Version: "3.23.1", + PURL: "pkg:maven/org.assertj/assertj-core@3.23.1", + Language: pkg.Java, + Type: pkg.JavaPkg, + FoundBy: pomCatalogerName, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.JavaArchive{ PomProperties: &pkg.JavaPomProperties{ GroupID: "org.assertj", @@ -543,12 +550,13 @@ func getCommonsTextExpectedPackages(resolved bool) expected { } commonsIO := pkg.Package{ - Name: "commons-io", - Version: "2.11.0", - PURL: "pkg:maven/commons-io/commons-io@2.11.0", - Language: pkg.Java, - Type: pkg.JavaPkg, - FoundBy: pomCatalogerName, + Name: "commons-io", + Version: "2.11.0", + PURL: "pkg:maven/commons-io/commons-io@2.11.0", + Language: pkg.Java, + Type: pkg.JavaPkg, + FoundBy: pomCatalogerName, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.JavaArchive{ PomProperties: &pkg.JavaPomProperties{ GroupID: "commons-io", @@ -559,12 +567,13 @@ func getCommonsTextExpectedPackages(resolved bool) expected { } mockitoInline := pkg.Package{ - Name: "mockito-inline", - Version: "4.8.0", - PURL: "pkg:maven/org.mockito/mockito-inline@4.8.0", - Language: pkg.Java, - Type: pkg.JavaPkg, - FoundBy: pomCatalogerName, + Name: "mockito-inline", + Version: "4.8.0", + PURL: "pkg:maven/org.mockito/mockito-inline@4.8.0", + Language: pkg.Java, + Type: pkg.JavaPkg, + FoundBy: pomCatalogerName, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.JavaArchive{ PomProperties: &pkg.JavaPomProperties{ GroupID: "org.mockito", @@ -575,12 +584,13 @@ func getCommonsTextExpectedPackages(resolved bool) expected { } js := pkg.Package{ - Name: "js", - Version: "22.0.0.2", - PURL: "pkg:maven/org.graalvm.js/js@22.0.0.2", - Language: pkg.Java, - Type: pkg.JavaPkg, - FoundBy: pomCatalogerName, + Name: "js", + Version: "22.0.0.2", + PURL: "pkg:maven/org.graalvm.js/js@22.0.0.2", + Language: pkg.Java, + Type: pkg.JavaPkg, + FoundBy: pomCatalogerName, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.JavaArchive{ PomProperties: &pkg.JavaPomProperties{ GroupID: "org.graalvm.js", @@ -591,12 +601,13 @@ func getCommonsTextExpectedPackages(resolved bool) expected { } jsScriptengine := pkg.Package{ - Name: "js-scriptengine", - Version: "22.0.0.2", - PURL: "pkg:maven/org.graalvm.js/js-scriptengine@22.0.0.2", - Language: pkg.Java, - Type: pkg.JavaPkg, - FoundBy: pomCatalogerName, + Name: "js-scriptengine", + Version: "22.0.0.2", + PURL: "pkg:maven/org.graalvm.js/js-scriptengine@22.0.0.2", + Language: pkg.Java, + Type: pkg.JavaPkg, + FoundBy: pomCatalogerName, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.JavaArchive{ PomProperties: &pkg.JavaPomProperties{ GroupID: "org.graalvm.js", @@ -607,12 +618,13 @@ func getCommonsTextExpectedPackages(resolved bool) expected { } commonsRngSimple := pkg.Package{ - Name: "commons-rng-simple", - Version: "1.4", - PURL: "pkg:maven/org.apache.commons/commons-rng-simple@1.4", - Language: pkg.Java, - Type: pkg.JavaPkg, - FoundBy: pomCatalogerName, + Name: "commons-rng-simple", + Version: "1.4", + PURL: "pkg:maven/org.apache.commons/commons-rng-simple@1.4", + Language: pkg.Java, + Type: pkg.JavaPkg, + FoundBy: pomCatalogerName, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.JavaArchive{ PomProperties: &pkg.JavaPomProperties{ GroupID: "org.apache.commons", @@ -623,12 +635,13 @@ func getCommonsTextExpectedPackages(resolved bool) expected { } jmhCore := pkg.Package{ - Name: "jmh-core", - Version: "1.35", - PURL: "pkg:maven/org.openjdk.jmh/jmh-core@1.35", - Language: pkg.Java, - Type: pkg.JavaPkg, - FoundBy: pomCatalogerName, + Name: "jmh-core", + Version: "1.35", + PURL: "pkg:maven/org.openjdk.jmh/jmh-core@1.35", + Language: pkg.Java, + Type: pkg.JavaPkg, + FoundBy: pomCatalogerName, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.JavaArchive{ PomProperties: &pkg.JavaPomProperties{ GroupID: "org.openjdk.jmh", @@ -639,12 +652,13 @@ func getCommonsTextExpectedPackages(resolved bool) expected { } jmhGeneratorAnnprocess := pkg.Package{ - Name: "jmh-generator-annprocess", - Version: "1.35", - PURL: "pkg:maven/org.openjdk.jmh/jmh-generator-annprocess@1.35", - Language: pkg.Java, - Type: pkg.JavaPkg, - FoundBy: pomCatalogerName, + Name: "jmh-generator-annprocess", + Version: "1.35", + PURL: "pkg:maven/org.openjdk.jmh/jmh-generator-annprocess@1.35", + Language: pkg.Java, + Type: pkg.JavaPkg, + FoundBy: pomCatalogerName, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.JavaArchive{ PomProperties: &pkg.JavaPomProperties{ GroupID: "org.openjdk.jmh", @@ -699,6 +713,8 @@ func expectedTransientPackageData() expected { transitiveTopLevel := pkg.Package{ Name: "transitive-top-level", Version: "99", + // one of the children is missing a pom in the test fixtures, this is a search miss + Dependencies: pkg.CompleteDependencies, Metadata: pkg.JavaArchive{ PomProject: &pkg.JavaPomProject{ GroupID: "my.other.group", @@ -708,9 +724,10 @@ func expectedTransientPackageData() expected { }, } childOne := pkg.Package{ - Name: "child-one", - Version: "1.3.6", - Licenses: epl2, + Name: "child-one", + Version: "1.3.6", + Licenses: epl2, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.JavaArchive{ PomProject: &pkg.JavaPomProject{ GroupID: "my.org", @@ -729,9 +746,10 @@ func expectedTransientPackageData() expected { }, } childTwo := pkg.Package{ - Name: "child-two", - Version: "2.1.90", - Licenses: epl2, + Name: "child-two", + Version: "2.1.90", + Licenses: epl2, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.JavaArchive{ PomProject: &pkg.JavaPomProject{ GroupID: "my.org", @@ -753,6 +771,8 @@ func expectedTransientPackageData() expected { commonsLang3_113_7_8_0 := pkg.Package{ Name: "commons-lang3", Version: "3.113.7.8.0", + // missing pom in test fixtures, this is a search miss + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.JavaArchive{ PomProperties: &pkg.JavaPomProperties{ GroupID: "org.apache.commons", @@ -763,6 +783,8 @@ func expectedTransientPackageData() expected { commonsLang3_12_0 := pkg.Package{ Name: "commons-lang3", Version: "3.12.0", + // missing pom in test fixtures, this is a search miss + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.JavaArchive{ PomProperties: &pkg.JavaPomProperties{ GroupID: "org.apache.commons", @@ -773,6 +795,8 @@ func expectedTransientPackageData() expected { commonsMath3 := pkg.Package{ Name: "commons-math3.11.0", Version: "3.5", + // missing pom in test fixtures, this is a search miss + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.JavaArchive{ PomProperties: &pkg.JavaPomProperties{ GroupID: "org.apache.commons", @@ -783,6 +807,8 @@ func expectedTransientPackageData() expected { commonsExec := pkg.Package{ Name: "commons-exec", Version: "1.3", + // missing pom in test fixtures, this is a search miss + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.JavaArchive{ PomProperties: &pkg.JavaPomProperties{ GroupID: "org.apache.commons", diff --git a/syft/pkg/cataloger/javascript/cataloger_test.go b/syft/pkg/cataloger/javascript/cataloger_test.go index 0adf2b4fd..73487782d 100644 --- a/syft/pkg/cataloger/javascript/cataloger_test.go +++ b/syft/pkg/cataloger/javascript/cataloger_test.go @@ -12,120 +12,131 @@ func Test_JavascriptCataloger(t *testing.T) { locationSet := file.NewLocationSet(file.NewLocation("package-lock.json")) expectedPkgs := []pkg.Package{ { - Name: "@actions/core", - Version: "1.6.0", - FoundBy: "javascript-lock-cataloger", - PURL: "pkg:npm/%40actions/core@1.6.0", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "@actions/core", + Version: "1.6.0", + FoundBy: "javascript-lock-cataloger", + PURL: "pkg:npm/%40actions/core@1.6.0", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("MIT", file.NewLocation("package-lock.json")), ), Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/@actions/core/-/core-1.6.0.tgz", Integrity: "sha512-NB1UAZomZlCV/LmJqkLhNTqtKfFXJZAUPcfl/zqG7EfsQdeUJtaWO98SGbuQ3pydJ3fHl2CvI/51OKYlCYYcaw=="}, }, { - Name: "ansi-regex", - Version: "3.0.0", - FoundBy: "javascript-lock-cataloger", - PURL: "pkg:npm/ansi-regex@3.0.0", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", Integrity: "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="}, + Name: "ansi-regex", + Version: "3.0.0", + FoundBy: "javascript-lock-cataloger", + PURL: "pkg:npm/ansi-regex@3.0.0", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", Integrity: "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="}, }, { - Name: "cowsay", - Version: "1.4.0", - FoundBy: "javascript-lock-cataloger", - PURL: "pkg:npm/cowsay@1.4.0", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "cowsay", + Version: "1.4.0", + FoundBy: "javascript-lock-cataloger", + PURL: "pkg:npm/cowsay@1.4.0", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("MIT", file.NewLocation("package-lock.json")), ), Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/cowsay/-/cowsay-1.4.0.tgz", Integrity: "sha512-rdg5k5PsHFVJheO/pmE3aDg2rUDDTfPJau6yYkZYlHFktUz+UxbE+IgnUAEyyCyv4noL5ltxXD0gZzmHPCy/9g=="}, }, { - Name: "get-stdin", - Version: "5.0.1", - FoundBy: "javascript-lock-cataloger", - PURL: "pkg:npm/get-stdin@5.0.1", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz", Integrity: "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g="}, + Name: "get-stdin", + Version: "5.0.1", + FoundBy: "javascript-lock-cataloger", + PURL: "pkg:npm/get-stdin@5.0.1", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz", Integrity: "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g="}, }, { - Name: "is-fullwidth-code-point", - Version: "2.0.0", - FoundBy: "javascript-lock-cataloger", - PURL: "pkg:npm/is-fullwidth-code-point@2.0.0", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", Integrity: "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="}, + Name: "is-fullwidth-code-point", + Version: "2.0.0", + FoundBy: "javascript-lock-cataloger", + PURL: "pkg:npm/is-fullwidth-code-point@2.0.0", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", Integrity: "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="}, }, { - Name: "minimist", - Version: "0.0.10", - FoundBy: "javascript-lock-cataloger", - PURL: "pkg:npm/minimist@0.0.10", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", Integrity: "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8="}, + Name: "minimist", + Version: "0.0.10", + FoundBy: "javascript-lock-cataloger", + PURL: "pkg:npm/minimist@0.0.10", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", Integrity: "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8="}, }, { - Name: "optimist", - Version: "0.6.1", - FoundBy: "javascript-lock-cataloger", - PURL: "pkg:npm/optimist@0.6.1", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", Integrity: "sha1-2j6nRob6IaGaERwybpDrFaAZZoY="}, + Name: "optimist", + Version: "0.6.1", + FoundBy: "javascript-lock-cataloger", + PURL: "pkg:npm/optimist@0.6.1", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", Integrity: "sha1-2j6nRob6IaGaERwybpDrFaAZZoY="}, }, { - Name: "string-width", - Version: "2.1.1", - FoundBy: "javascript-lock-cataloger", - PURL: "pkg:npm/string-width@2.1.1", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", Integrity: "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw=="}, + Name: "string-width", + Version: "2.1.1", + FoundBy: "javascript-lock-cataloger", + PURL: "pkg:npm/string-width@2.1.1", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", Integrity: "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw=="}, }, { - Name: "strip-ansi", - Version: "4.0.0", - FoundBy: "javascript-lock-cataloger", - PURL: "pkg:npm/strip-ansi@4.0.0", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", Integrity: "sha1-qEeQIusaw2iocTibY1JixQXuNo8="}, + Name: "strip-ansi", + Version: "4.0.0", + FoundBy: "javascript-lock-cataloger", + PURL: "pkg:npm/strip-ansi@4.0.0", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", Integrity: "sha1-qEeQIusaw2iocTibY1JixQXuNo8="}, }, { - Name: "strip-eof", - Version: "1.0.0", - FoundBy: "javascript-lock-cataloger", - PURL: "pkg:npm/strip-eof@1.0.0", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", Integrity: "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8="}, + Name: "strip-eof", + Version: "1.0.0", + FoundBy: "javascript-lock-cataloger", + PURL: "pkg:npm/strip-eof@1.0.0", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", Integrity: "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8="}, }, { - Name: "wordwrap", - Version: "0.0.3", - FoundBy: "javascript-lock-cataloger", - PURL: "pkg:npm/wordwrap@0.0.3", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", Integrity: "sha1-o9XabNXAvAAI03I0u68b7WMFkQc="}, + Name: "wordwrap", + Version: "0.0.3", + FoundBy: "javascript-lock-cataloger", + PURL: "pkg:npm/wordwrap@0.0.3", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", Integrity: "sha1-o9XabNXAvAAI03I0u68b7WMFkQc="}, }, } diff --git a/syft/pkg/cataloger/javascript/package.go b/syft/pkg/cataloger/javascript/package.go index 19114c99f..a9841b09e 100644 --- a/syft/pkg/cataloger/javascript/package.go +++ b/syft/pkg/cataloger/javascript/package.go @@ -32,6 +32,9 @@ func newPackageJSONPackage(u packageJSON, indexLocation file.Location) pkg.Packa Language: pkg.JavaScript, Licenses: pkg.NewLicenseSet(license...), Type: pkg.NpmPkg, + // though we could glean dependency information from the package.json and surrounding packages found in a node_modules directory, + // we do not do so today, so we mark knowledge of dependencies as incomplete. + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.NpmPackage{ Name: u.Name, Version: u.Version, @@ -88,7 +91,10 @@ func newPackageLockV1Package(cfg CatalogerConfig, resolver file.Resolver, locati PURL: packageURL(name, version), Language: pkg.JavaScript, Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: u.Resolved, Integrity: u.Integrity}, + // though we could glean dependency information from the package-lock.json, + // we do not do so today, so we mark knowledge of dependencies as incomplete. + Dependencies: pkg.IncompleteDependencies, + Metadata: pkg.NpmPackageLockEntry{Resolved: u.Resolved, Integrity: u.Integrity}, }, ) } @@ -120,7 +126,10 @@ func newPackageLockV2Package(cfg CatalogerConfig, resolver file.Resolver, locati PURL: packageURL(name, u.Version), Language: pkg.JavaScript, Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: u.Resolved, Integrity: u.Integrity}, + // though we could glean dependency information from the package-lock.json, + // we do not do so today, so we mark knowledge of dependencies as incomplete. + Dependencies: pkg.IncompleteDependencies, + Metadata: pkg.NpmPackageLockEntry{Resolved: u.Resolved, Integrity: u.Integrity}, }, ) } @@ -136,6 +145,9 @@ func newPnpmPackage(resolver file.Resolver, location file.Location, name, versio PURL: packageURL(name, version), Language: pkg.JavaScript, Type: pkg.NpmPkg, + // though we could glean dependency information from the pnpm files, + // we do not do so today, so we mark knowledge of dependencies as incomplete. + Dependencies: pkg.IncompleteDependencies, }, ) } @@ -164,7 +176,10 @@ func newYarnLockPackage(cfg CatalogerConfig, resolver file.Resolver, location fi PURL: packageURL(name, version), Language: pkg.JavaScript, Type: pkg.NpmPkg, - Metadata: pkg.YarnLockEntry{Resolved: resolved, Integrity: integrity}, + // though we could glean dependency information from the yarn.lock, + // we do not do so today, so we mark knowledge of dependencies as incomplete. + Dependencies: pkg.IncompleteDependencies, + Metadata: pkg.YarnLockEntry{Resolved: resolved, Integrity: integrity}, }, ) } diff --git a/syft/pkg/cataloger/javascript/parse_package_json_test.go b/syft/pkg/cataloger/javascript/parse_package_json_test.go index ea0102d98..fb7d0c4f2 100644 --- a/syft/pkg/cataloger/javascript/parse_package_json_test.go +++ b/syft/pkg/cataloger/javascript/parse_package_json_test.go @@ -26,6 +26,7 @@ func TestParsePackageJSON(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("Artistic-2.0", file.NewLocation("test-fixtures/pkg-json/package.json")), ), + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.NpmPackage{ Name: "npm", Version: "6.14.6", @@ -47,6 +48,7 @@ func TestParsePackageJSON(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("ISC", file.NewLocation("test-fixtures/pkg-json/package-license-object.json")), ), + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.NpmPackage{ Name: "npm", Version: "6.14.6", @@ -68,7 +70,8 @@ func TestParsePackageJSON(t *testing.T) { pkg.NewLicenseFromLocations("MIT", file.NewLocation("test-fixtures/pkg-json/package-license-objects.json")), pkg.NewLicenseFromLocations("Apache-2.0", file.NewLocation("test-fixtures/pkg-json/package-license-objects.json")), ), - Language: pkg.JavaScript, + Language: pkg.JavaScript, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.NpmPackage{ Name: "npm", Version: "6.14.6", @@ -82,11 +85,12 @@ func TestParsePackageJSON(t *testing.T) { { Fixture: "test-fixtures/pkg-json/package-malformed-license.json", ExpectedPkg: pkg.Package{ - Name: "npm", - Version: "6.14.6", - PURL: "pkg:npm/npm@6.14.6", - Type: pkg.NpmPkg, - Language: pkg.JavaScript, + Name: "npm", + Version: "6.14.6", + PURL: "pkg:npm/npm@6.14.6", + Type: pkg.NpmPkg, + Language: pkg.JavaScript, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.NpmPackage{ Name: "npm", Version: "6.14.6", @@ -100,11 +104,12 @@ func TestParsePackageJSON(t *testing.T) { { Fixture: "test-fixtures/pkg-json/package-no-license.json", ExpectedPkg: pkg.Package{ - Name: "npm", - Version: "6.14.6", - PURL: "pkg:npm/npm@6.14.6", - Type: pkg.NpmPkg, - Language: pkg.JavaScript, + Name: "npm", + Version: "6.14.6", + PURL: "pkg:npm/npm@6.14.6", + Type: pkg.NpmPkg, + Language: pkg.JavaScript, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.NpmPackage{ Name: "npm", Version: "6.14.6", @@ -125,7 +130,8 @@ func TestParsePackageJSON(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("Artistic-2.0", file.NewLocation("test-fixtures/pkg-json/package-nested-author.json")), ), - Language: pkg.JavaScript, + Language: pkg.JavaScript, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.NpmPackage{ Name: "npm", Version: "6.14.6", @@ -146,7 +152,8 @@ func TestParsePackageJSON(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("MIT", file.NewLocation("test-fixtures/pkg-json/package-repo-string.json")), ), - Language: pkg.JavaScript, + Language: pkg.JavaScript, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.NpmPackage{ Name: "function-bind", Version: "1.1.1", @@ -167,7 +174,8 @@ func TestParsePackageJSON(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("Artistic-2.0", file.NewLocation("test-fixtures/pkg-json/package-private.json")), ), - Language: pkg.JavaScript, + Language: pkg.JavaScript, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.NpmPackage{ Name: "npm", Version: "6.14.6", @@ -189,7 +197,8 @@ func TestParsePackageJSON(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("Artistic-2.0", file.NewLocation("test-fixtures/pkg-json/package-author-non-standard.json")), ), - Language: pkg.JavaScript, + Language: pkg.JavaScript, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.NpmPackage{ Name: "npm", Version: "6.14.6", @@ -224,11 +233,12 @@ func TestParsePackageJSON_Partial(t *testing.T) { // see https://github.com/anch // according to compliance rules later expectedPkgs := []pkg.Package{ { - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - PURL: packageURL("", ""), - Metadata: pkg.NpmPackage{}, - Locations: file.NewLocationSet(file.NewLocation(fixtureFile)), + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + PURL: packageURL("", ""), + Locations: file.NewLocationSet(file.NewLocation(fixtureFile)), + Dependencies: pkg.IncompleteDependencies, + Metadata: pkg.NpmPackage{}, }, } pkgtest.TestFileParser(t, fixtureFile, parsePackageJSON, expectedPkgs, nil) diff --git a/syft/pkg/cataloger/javascript/parse_package_lock_test.go b/syft/pkg/cataloger/javascript/parse_package_lock_test.go index b3ba527bb..4ca50bbd5 100644 --- a/syft/pkg/cataloger/javascript/parse_package_lock_test.go +++ b/syft/pkg/cataloger/javascript/parse_package_lock_test.go @@ -13,92 +13,103 @@ func TestParsePackageLock(t *testing.T) { var expectedRelationships []artifact.Relationship expectedPkgs := []pkg.Package{ { - Name: "@actions/core", - Version: "1.6.0", - PURL: "pkg:npm/%40actions/core@1.6.0", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/@actions/core/-/core-1.6.0.tgz", Integrity: "sha512-NB1UAZomZlCV/LmJqkLhNTqtKfFXJZAUPcfl/zqG7EfsQdeUJtaWO98SGbuQ3pydJ3fHl2CvI/51OKYlCYYcaw=="}, + Name: "@actions/core", + Version: "1.6.0", + PURL: "pkg:npm/%40actions/core@1.6.0", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/@actions/core/-/core-1.6.0.tgz", Integrity: "sha512-NB1UAZomZlCV/LmJqkLhNTqtKfFXJZAUPcfl/zqG7EfsQdeUJtaWO98SGbuQ3pydJ3fHl2CvI/51OKYlCYYcaw=="}, }, { - Name: "ansi-regex", - Version: "3.0.0", - PURL: "pkg:npm/ansi-regex@3.0.0", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", Integrity: "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="}, + Name: "ansi-regex", + Version: "3.0.0", + PURL: "pkg:npm/ansi-regex@3.0.0", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", Integrity: "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="}, }, { - Name: "cowsay", - Version: "1.4.0", - PURL: "pkg:npm/cowsay@1.4.0", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/cowsay/-/cowsay-1.4.0.tgz", Integrity: "sha512-rdg5k5PsHFVJheO/pmE3aDg2rUDDTfPJau6yYkZYlHFktUz+UxbE+IgnUAEyyCyv4noL5ltxXD0gZzmHPCy/9g=="}, + Name: "cowsay", + Version: "1.4.0", + PURL: "pkg:npm/cowsay@1.4.0", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/cowsay/-/cowsay-1.4.0.tgz", Integrity: "sha512-rdg5k5PsHFVJheO/pmE3aDg2rUDDTfPJau6yYkZYlHFktUz+UxbE+IgnUAEyyCyv4noL5ltxXD0gZzmHPCy/9g=="}, }, { - Name: "get-stdin", - Version: "5.0.1", - PURL: "pkg:npm/get-stdin@5.0.1", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz", Integrity: "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g="}, + Name: "get-stdin", + Version: "5.0.1", + PURL: "pkg:npm/get-stdin@5.0.1", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz", Integrity: "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g="}, }, { - Name: "is-fullwidth-code-point", - Version: "2.0.0", - PURL: "pkg:npm/is-fullwidth-code-point@2.0.0", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", Integrity: "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="}, + Name: "is-fullwidth-code-point", + Version: "2.0.0", + PURL: "pkg:npm/is-fullwidth-code-point@2.0.0", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", Integrity: "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="}, }, { - Name: "minimist", - Version: "0.0.10", - PURL: "pkg:npm/minimist@0.0.10", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", Integrity: "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8="}, + Name: "minimist", + Version: "0.0.10", + PURL: "pkg:npm/minimist@0.0.10", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", Integrity: "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8="}, }, { - Name: "optimist", - Version: "0.6.1", - PURL: "pkg:npm/optimist@0.6.1", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", Integrity: "sha1-2j6nRob6IaGaERwybpDrFaAZZoY="}, + Name: "optimist", + Version: "0.6.1", + PURL: "pkg:npm/optimist@0.6.1", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", Integrity: "sha1-2j6nRob6IaGaERwybpDrFaAZZoY="}, }, { - Name: "string-width", - Version: "2.1.1", - PURL: "pkg:npm/string-width@2.1.1", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", Integrity: "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw=="}, + Name: "string-width", + Version: "2.1.1", + PURL: "pkg:npm/string-width@2.1.1", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", Integrity: "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw=="}, }, { - Name: "strip-ansi", - Version: "4.0.0", - PURL: "pkg:npm/strip-ansi@4.0.0", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", Integrity: "sha1-qEeQIusaw2iocTibY1JixQXuNo8="}, + Name: "strip-ansi", + Version: "4.0.0", + PURL: "pkg:npm/strip-ansi@4.0.0", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", Integrity: "sha1-qEeQIusaw2iocTibY1JixQXuNo8="}, }, { - Name: "strip-eof", - Version: "1.0.0", - PURL: "pkg:npm/strip-eof@1.0.0", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", Integrity: "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8="}, + Name: "strip-eof", + Version: "1.0.0", + PURL: "pkg:npm/strip-eof@1.0.0", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", Integrity: "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8="}, }, { - Name: "wordwrap", - Version: "0.0.3", - PURL: "pkg:npm/wordwrap@0.0.3", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", Integrity: "sha1-o9XabNXAvAAI03I0u68b7WMFkQc="}, + Name: "wordwrap", + Version: "0.0.3", + PURL: "pkg:npm/wordwrap@0.0.3", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", Integrity: "sha1-o9XabNXAvAAI03I0u68b7WMFkQc="}, }, } fixture := "test-fixtures/pkg-lock/package-lock.json" @@ -115,52 +126,57 @@ func TestParsePackageLockV2(t *testing.T) { var expectedRelationships []artifact.Relationship expectedPkgs := []pkg.Package{ { - Name: "npm", - Version: "6.14.6", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - PURL: "pkg:npm/npm@6.14.6", - Metadata: pkg.NpmPackageLockEntry{}, + Name: "npm", + Version: "6.14.6", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, + PURL: "pkg:npm/npm@6.14.6", + Metadata: pkg.NpmPackageLockEntry{}, }, { - Name: "@types/prop-types", - Version: "15.7.5", - PURL: "pkg:npm/%40types/prop-types@15.7.5", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "@types/prop-types", + Version: "15.7.5", + PURL: "pkg:npm/%40types/prop-types@15.7.5", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("MIT", file.NewLocation(fixture)), ), Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", Integrity: "sha1-XxnSuFqY6VWANvajysyIGUIPBc8="}, }, { - Name: "@types/react", - Version: "18.0.17", - PURL: "pkg:npm/%40types/react@18.0.17", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "@types/react", + Version: "18.0.17", + PURL: "pkg:npm/%40types/react@18.0.17", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("MIT", file.NewLocation(fixture)), ), Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/@types/react/-/react-18.0.17.tgz", Integrity: "sha1-RYPZwyLWfv5LOak10iPtzHBQzPQ="}, }, { - Name: "@types/scheduler", - Version: "0.16.2", - PURL: "pkg:npm/%40types/scheduler@0.16.2", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "@types/scheduler", + Version: "0.16.2", + PURL: "pkg:npm/%40types/scheduler@0.16.2", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("MIT", file.NewLocation(fixture)), ), Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", Integrity: "sha1-GmL4lSVyPd4kuhsBsJK/XfitTTk="}, }, { - Name: "csstype", - Version: "3.1.0", - PURL: "pkg:npm/csstype@3.1.0", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "csstype", + Version: "3.1.0", + PURL: "pkg:npm/csstype@3.1.0", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("MIT", file.NewLocation(fixture)), ), @@ -179,44 +195,49 @@ func TestParsePackageLockV3(t *testing.T) { var expectedRelationships []artifact.Relationship expectedPkgs := []pkg.Package{ { - Name: "lock-v3-fixture", - Version: "1.0.0", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - PURL: "pkg:npm/lock-v3-fixture@1.0.0", - Metadata: pkg.NpmPackageLockEntry{}, + Name: "lock-v3-fixture", + Version: "1.0.0", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, + PURL: "pkg:npm/lock-v3-fixture@1.0.0", + Metadata: pkg.NpmPackageLockEntry{}, }, { - Name: "@types/prop-types", - Version: "15.7.5", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - PURL: "pkg:npm/%40types/prop-types@15.7.5", - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", Integrity: "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w=="}, + Name: "@types/prop-types", + Version: "15.7.5", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, + PURL: "pkg:npm/%40types/prop-types@15.7.5", + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", Integrity: "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w=="}, }, { - Name: "@types/react", - Version: "18.0.20", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - PURL: "pkg:npm/%40types/react@18.0.20", - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/@types/react/-/react-18.0.20.tgz", Integrity: "sha512-MWul1teSPxujEHVwZl4a5HxQ9vVNsjTchVA+xRqv/VYGCuKGAU6UhfrTdF5aBefwD1BHUD8i/zq+O/vyCm/FrA=="}, + Name: "@types/react", + Version: "18.0.20", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, + PURL: "pkg:npm/%40types/react@18.0.20", + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/@types/react/-/react-18.0.20.tgz", Integrity: "sha512-MWul1teSPxujEHVwZl4a5HxQ9vVNsjTchVA+xRqv/VYGCuKGAU6UhfrTdF5aBefwD1BHUD8i/zq+O/vyCm/FrA=="}, }, { - Name: "@types/scheduler", - Version: "0.16.2", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - PURL: "pkg:npm/%40types/scheduler@0.16.2", - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", Integrity: "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew=="}, + Name: "@types/scheduler", + Version: "0.16.2", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, + PURL: "pkg:npm/%40types/scheduler@0.16.2", + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", Integrity: "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew=="}, }, { - Name: "csstype", - Version: "3.1.1", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - PURL: "pkg:npm/csstype@3.1.1", - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz", Integrity: "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw=="}, + Name: "csstype", + Version: "3.1.1", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + PURL: "pkg:npm/csstype@3.1.1", + Dependencies: pkg.IncompleteDependencies, + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz", Integrity: "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw=="}, }, } for i := range expectedPkgs { @@ -230,28 +251,31 @@ func TestParsePackageLockAlias(t *testing.T) { var expectedRelationships []artifact.Relationship commonPkgs := []pkg.Package{ { - Name: "case", - Version: "1.6.2", - PURL: "pkg:npm/case@1.6.2", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/case/-/case-1.6.2.tgz", Integrity: "sha512-ll380ZRoraT7mUK2G92UbH+FJVD5AwdVIAYk9xhV1tauh0carDgYByUD1HhjCWsWgxrfQvCeHvtfj7IYR6TKeg=="}, + Name: "case", + Version: "1.6.2", + PURL: "pkg:npm/case@1.6.2", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/case/-/case-1.6.2.tgz", Integrity: "sha512-ll380ZRoraT7mUK2G92UbH+FJVD5AwdVIAYk9xhV1tauh0carDgYByUD1HhjCWsWgxrfQvCeHvtfj7IYR6TKeg=="}, }, { - Name: "case", - Version: "1.6.3", - PURL: "pkg:npm/case@1.6.3", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/case/-/case-1.6.3.tgz", Integrity: "sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ=="}, + Name: "case", + Version: "1.6.3", + PURL: "pkg:npm/case@1.6.3", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/case/-/case-1.6.3.tgz", Integrity: "sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ=="}, }, { - Name: "@bundled-es-modules/chai", - Version: "4.2.2", - PURL: "pkg:npm/%40bundled-es-modules/chai@4.2.2", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/@bundled-es-modules/chai/-/chai-4.2.2.tgz", Integrity: "sha512-iGmVYw2/zJCoqyKTtWEYCtFmMyi8WmACQKtky0lpNyEKWX0YIOpKWGD7saMXL+tPpllss0otilxV0SLwyi3Ytg=="}, + Name: "@bundled-es-modules/chai", + Version: "4.2.2", + PURL: "pkg:npm/%40bundled-es-modules/chai@4.2.2", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/@bundled-es-modules/chai/-/chai-4.2.2.tgz", Integrity: "sha512-iGmVYw2/zJCoqyKTtWEYCtFmMyi8WmACQKtky0lpNyEKWX0YIOpKWGD7saMXL+tPpllss0otilxV0SLwyi3Ytg=="}, }, } @@ -268,7 +292,8 @@ func TestParsePackageLockAlias(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("ISC", file.NewLocation(packageLockV2)), ), - Metadata: pkg.NpmPackageLockEntry{}, + Dependencies: pkg.IncompleteDependencies, + Metadata: pkg.NpmPackageLockEntry{}, } for _, pl := range packageLocks { @@ -292,10 +317,11 @@ func TestParsePackageLockLicenseWithArray(t *testing.T) { var expectedRelationships []artifact.Relationship expectedPkgs := []pkg.Package{ { - Name: "tmp", - Version: "1.0.0", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "tmp", + Version: "1.0.0", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("ISC", file.NewLocation(fixture)), ), @@ -303,11 +329,11 @@ func TestParsePackageLockLicenseWithArray(t *testing.T) { Metadata: pkg.NpmPackageLockEntry{}, }, { - Name: "pause-stream", - Version: "0.0.11", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - + Name: "pause-stream", + Version: "0.0.11", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("MIT", file.NewLocation(fixture)), pkg.NewLicenseFromLocations("Apache2", file.NewLocation(fixture)), @@ -316,10 +342,11 @@ func TestParsePackageLockLicenseWithArray(t *testing.T) { Metadata: pkg.NpmPackageLockEntry{}, }, { - Name: "through", - Version: "2.3.8", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "through", + Version: "2.3.8", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("MIT", file.NewLocation(fixture)), ), diff --git a/syft/pkg/cataloger/javascript/parse_pnpm_lock_test.go b/syft/pkg/cataloger/javascript/parse_pnpm_lock_test.go index 8b5ed7d0a..f0bc65055 100644 --- a/syft/pkg/cataloger/javascript/parse_pnpm_lock_test.go +++ b/syft/pkg/cataloger/javascript/parse_pnpm_lock_test.go @@ -17,36 +17,40 @@ func TestParsePnpmLock(t *testing.T) { expectedPkgs := []pkg.Package{ { - Name: "nanoid", - Version: "3.3.4", - PURL: "pkg:npm/nanoid@3.3.4", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "nanoid", + Version: "3.3.4", + PURL: "pkg:npm/nanoid@3.3.4", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, }, { - Name: "picocolors", - Version: "1.0.0", - PURL: "pkg:npm/picocolors@1.0.0", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "picocolors", + Version: "1.0.0", + PURL: "pkg:npm/picocolors@1.0.0", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, }, { - Name: "source-map-js", - Version: "1.0.2", - PURL: "pkg:npm/source-map-js@1.0.2", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "source-map-js", + Version: "1.0.2", + PURL: "pkg:npm/source-map-js@1.0.2", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, }, { - Name: "@bcoe/v8-coverage", - Version: "0.2.3", - PURL: "pkg:npm/%40bcoe/v8-coverage@0.2.3", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "@bcoe/v8-coverage", + Version: "0.2.3", + PURL: "pkg:npm/%40bcoe/v8-coverage@0.2.3", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, }, } @@ -61,84 +65,94 @@ func TestParsePnpmV6Lock(t *testing.T) { expectedPkgs := []pkg.Package{ { - Name: "@testing-library/jest-dom", - Version: "5.16.5", - PURL: "pkg:npm/%40testing-library/jest-dom@5.16.5", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "@testing-library/jest-dom", + Version: "5.16.5", + PURL: "pkg:npm/%40testing-library/jest-dom@5.16.5", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, }, { - Name: "@testing-library/react", - Version: "13.4.0", - PURL: "pkg:npm/%40testing-library/react@13.4.0", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "@testing-library/react", + Version: "13.4.0", + PURL: "pkg:npm/%40testing-library/react@13.4.0", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, }, { - Name: "@testing-library/user-event", - Version: "13.5.0", - PURL: "pkg:npm/%40testing-library/user-event@13.5.0", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "@testing-library/user-event", + Version: "13.5.0", + PURL: "pkg:npm/%40testing-library/user-event@13.5.0", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, }, { - Name: "react", - Version: "18.2.0", - PURL: "pkg:npm/react@18.2.0", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "react", + Version: "18.2.0", + PURL: "pkg:npm/react@18.2.0", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, }, { - Name: "react-dom", - Version: "18.2.0", - PURL: "pkg:npm/react-dom@18.2.0", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "react-dom", + Version: "18.2.0", + PURL: "pkg:npm/react-dom@18.2.0", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, }, { - Name: "web-vitals", - Version: "2.1.4", - PURL: "pkg:npm/web-vitals@2.1.4", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "web-vitals", + Version: "2.1.4", + PURL: "pkg:npm/web-vitals@2.1.4", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, }, { - Name: "@babel/core", - Version: "7.21.4", - PURL: "pkg:npm/%40babel/core@7.21.4", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "@babel/core", + Version: "7.21.4", + PURL: "pkg:npm/%40babel/core@7.21.4", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, }, { - Name: "@types/eslint", - Version: "8.37.0", - PURL: "pkg:npm/%40types/eslint@8.37.0", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "@types/eslint", + Version: "8.37.0", + PURL: "pkg:npm/%40types/eslint@8.37.0", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, }, { - Name: "read-cache", - Version: "1.0.0", - PURL: "pkg:npm/read-cache@1.0.0", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "read-cache", + Version: "1.0.0", + PURL: "pkg:npm/read-cache@1.0.0", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, }, { - Name: "schema-utils", - Version: "3.1.2", - PURL: "pkg:npm/schema-utils@3.1.2", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "schema-utils", + Version: "3.1.2", + PURL: "pkg:npm/schema-utils@3.1.2", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, }, } diff --git a/syft/pkg/cataloger/javascript/parse_yarn_lock_test.go b/syft/pkg/cataloger/javascript/parse_yarn_lock_test.go index 20fac12fe..866a1ed4e 100644 --- a/syft/pkg/cataloger/javascript/parse_yarn_lock_test.go +++ b/syft/pkg/cataloger/javascript/parse_yarn_lock_test.go @@ -22,85 +22,94 @@ func TestParseYarnBerry(t *testing.T) { expectedPkgs := []pkg.Package{ { - Name: "@babel/code-frame", - Version: "7.10.4", - Locations: locations, - PURL: "pkg:npm/%40babel/code-frame@7.10.4", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.YarnLockEntry{}, + Name: "@babel/code-frame", + Version: "7.10.4", + Locations: locations, + PURL: "pkg:npm/%40babel/code-frame@7.10.4", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, + Metadata: pkg.YarnLockEntry{}, }, { - Name: "@types/minimatch", - Version: "3.0.3", - Locations: locations, - PURL: "pkg:npm/%40types/minimatch@3.0.3", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.YarnLockEntry{}, + Name: "@types/minimatch", + Version: "3.0.3", + Locations: locations, + PURL: "pkg:npm/%40types/minimatch@3.0.3", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, + Metadata: pkg.YarnLockEntry{}, }, { - Name: "@types/qs", - Version: "6.9.4", - Locations: locations, - PURL: "pkg:npm/%40types/qs@6.9.4", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.YarnLockEntry{}, + Name: "@types/qs", + Version: "6.9.4", + Locations: locations, + PURL: "pkg:npm/%40types/qs@6.9.4", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, + Metadata: pkg.YarnLockEntry{}, }, { - Name: "ajv", - Version: "6.12.3", - Locations: locations, - PURL: "pkg:npm/ajv@6.12.3", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.YarnLockEntry{}, + Name: "ajv", + Version: "6.12.3", + Locations: locations, + PURL: "pkg:npm/ajv@6.12.3", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, + Metadata: pkg.YarnLockEntry{}, }, { - Name: "asn1.js", - Version: "4.10.1", - Locations: locations, - PURL: "pkg:npm/asn1.js@4.10.1", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.YarnLockEntry{}, + Name: "asn1.js", + Version: "4.10.1", + Locations: locations, + PURL: "pkg:npm/asn1.js@4.10.1", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, + Metadata: pkg.YarnLockEntry{}, }, { - Name: "atob", - Version: "2.1.2", - Locations: locations, - PURL: "pkg:npm/atob@2.1.2", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.YarnLockEntry{}, + Name: "atob", + Version: "2.1.2", + Locations: locations, + PURL: "pkg:npm/atob@2.1.2", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, + Metadata: pkg.YarnLockEntry{}, }, { - Name: "aws-sdk", - Version: "2.706.0", - PURL: "pkg:npm/aws-sdk@2.706.0", - Locations: locations, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.YarnLockEntry{}, + Name: "aws-sdk", + Version: "2.706.0", + PURL: "pkg:npm/aws-sdk@2.706.0", + Locations: locations, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, + Metadata: pkg.YarnLockEntry{}, }, { - Name: "c0n-fab_u.laTION", - Version: "7.7.7", - Locations: locations, - PURL: "pkg:npm/c0n-fab_u.laTION@7.7.7", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.YarnLockEntry{}, + Name: "c0n-fab_u.laTION", + Version: "7.7.7", + Locations: locations, + PURL: "pkg:npm/c0n-fab_u.laTION@7.7.7", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, + Metadata: pkg.YarnLockEntry{}, }, { - Name: "jhipster-core", - Version: "7.3.4", - Locations: locations, - PURL: "pkg:npm/jhipster-core@7.3.4", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.YarnLockEntry{}, + Name: "jhipster-core", + Version: "7.3.4", + Locations: locations, + PURL: "pkg:npm/jhipster-core@7.3.4", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, + Metadata: pkg.YarnLockEntry{}, }, } @@ -115,60 +124,65 @@ func TestParseYarnLock(t *testing.T) { expectedPkgs := []pkg.Package{ { - Name: "@babel/code-frame", - Version: "7.10.4", - Locations: locations, - PURL: "pkg:npm/%40babel/code-frame@7.10.4", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "@babel/code-frame", + Version: "7.10.4", + Locations: locations, + PURL: "pkg:npm/%40babel/code-frame@7.10.4", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.YarnLockEntry{ Resolved: "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a", Integrity: "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", }, }, { - Name: "@types/minimatch", - Version: "3.0.3", - Locations: locations, - PURL: "pkg:npm/%40types/minimatch@3.0.3", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "@types/minimatch", + Version: "3.0.3", + Locations: locations, + PURL: "pkg:npm/%40types/minimatch@3.0.3", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.YarnLockEntry{ Resolved: "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d", Integrity: "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", }, }, { - Name: "@types/qs", - Version: "6.9.4", - Locations: locations, - PURL: "pkg:npm/%40types/qs@6.9.4", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "@types/qs", + Version: "6.9.4", + Locations: locations, + PURL: "pkg:npm/%40types/qs@6.9.4", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.YarnLockEntry{ Resolved: "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.4.tgz#a59e851c1ba16c0513ea123830dd639a0a15cb6a", Integrity: "sha512-+wYo+L6ZF6BMoEjtf8zB2esQsqdV6WsjRK/GP9WOgLPrq87PbNWgIxS76dS5uvl/QXtHGakZmwTznIfcPXcKlQ==", }, }, { - Name: "ajv", - Version: "6.12.3", - Locations: locations, - PURL: "pkg:npm/ajv@6.12.3", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "ajv", + Version: "6.12.3", + Locations: locations, + PURL: "pkg:npm/ajv@6.12.3", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.YarnLockEntry{ Resolved: "https://registry.yarnpkg.com/ajv/-/ajv-6.12.3.tgz#18c5af38a111ddeb4f2697bd78d68abc1cabd706", Integrity: "sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA==", }, }, { - Name: "asn1.js", - Version: "4.10.1", - Locations: locations, - PURL: "pkg:npm/asn1.js@4.10.1", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "asn1.js", + Version: "4.10.1", + Locations: locations, + PURL: "pkg:npm/asn1.js@4.10.1", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.YarnLockEntry{ Resolved: "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0", Integrity: "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", @@ -179,45 +193,49 @@ func TestParseYarnLock(t *testing.T) { Version: "2.1.2", Locations: locations, - PURL: "pkg:npm/atob@2.1.2", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + PURL: "pkg:npm/atob@2.1.2", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.YarnLockEntry{ Resolved: "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9", Integrity: "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", }, }, { - Name: "aws-sdk", - Version: "2.706.0", - Locations: locations, - PURL: "pkg:npm/aws-sdk@2.706.0", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "aws-sdk", + Version: "2.706.0", + Locations: locations, + PURL: "pkg:npm/aws-sdk@2.706.0", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.YarnLockEntry{ Resolved: "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.706.0.tgz#09f65e9a91ecac5a635daf934082abae30eca953", Integrity: "sha512-7GT+yrB5Wb/zOReRdv/Pzkb2Qt+hz6B/8FGMVaoysX3NryHvQUdz7EQWi5yhg9CxOjKxdw5lFwYSs69YlSp1KA==", }, }, { - Name: "jhipster-core", - Version: "7.3.4", - Locations: locations, - PURL: "pkg:npm/jhipster-core@7.3.4", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "jhipster-core", + Version: "7.3.4", + Locations: locations, + PURL: "pkg:npm/jhipster-core@7.3.4", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.YarnLockEntry{ Resolved: "https://registry.yarnpkg.com/jhipster-core/-/jhipster-core-7.3.4.tgz#c34b8c97c7f4e8b7518dae015517e2112c73cc80", Integrity: "sha512-AUhT69kNkqppaJZVfan/xnKG4Gs9Ggj7YLtTZFVe+xg+THrbMb5Ng7PL07PDlDw4KAEA33GMCwuAf65E8EpC4g==", }, }, { - Name: "something-i-made-up", - Version: "7.7.7", - Locations: locations, - PURL: "pkg:npm/something-i-made-up@7.7.7", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "something-i-made-up", + Version: "7.7.7", + Locations: locations, + PURL: "pkg:npm/something-i-made-up@7.7.7", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.YarnLockEntry{ Resolved: "https://registry.yarnpkg.com/something-i-made-up/-/c0n-fab_u.laTION-7.7.7.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0", Integrity: "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", @@ -258,13 +276,14 @@ func TestSearchYarnForLicenses(t *testing.T) { }, expectedPackages: []pkg.Package{ { - Name: "@babel/code-frame", - Version: "7.10.4", - Locations: locations, - PURL: "pkg:npm/%40babel/code-frame@7.10.4", - Licenses: pkg.NewLicenseSet(pkg.NewLicense("MIT")), - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "@babel/code-frame", + Version: "7.10.4", + Locations: locations, + PURL: "pkg:npm/%40babel/code-frame@7.10.4", + Licenses: pkg.NewLicenseSet(pkg.NewLicense("MIT")), + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.YarnLockEntry{ Resolved: "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a", Integrity: "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", diff --git a/syft/pkg/cataloger/kernel/cataloger_test.go b/syft/pkg/cataloger/kernel/cataloger_test.go index a440c7981..028e888c1 100644 --- a/syft/pkg/cataloger/kernel/cataloger_test.go +++ b/syft/pkg/cataloger/kernel/cataloger_test.go @@ -21,9 +21,10 @@ func Test_KernelCataloger(t *testing.T) { "/lib/modules/6.0.7-301.fc37.x86_64/vmlinuz", ), ), - Type: pkg.LinuxKernelPkg, - PURL: "pkg:generic/linux-kernel@6.0.7-301.fc37.x86_64", - CPEs: []cpe.CPE{cpe.Must("cpe:2.3:o:linux:linux_kernel:6.0.7-301.fc37.x86_64:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource)}, + Type: pkg.LinuxKernelPkg, + PURL: "pkg:generic/linux-kernel@6.0.7-301.fc37.x86_64", + CPEs: []cpe.CPE{cpe.Must("cpe:2.3:o:linux:linux_kernel:6.0.7-301.fc37.x86_64:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource)}, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.LinuxKernel{ Name: "", Architecture: "x86", @@ -56,8 +57,9 @@ func Test_KernelCataloger(t *testing.T) { ), ), ), - Type: pkg.LinuxKernelModulePkg, - PURL: "pkg:generic/ttynull", + Type: pkg.LinuxKernelModulePkg, + PURL: "pkg:generic/ttynull", + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.LinuxKernelModule{ Name: "ttynull", Version: "", diff --git a/syft/pkg/cataloger/kernel/package.go b/syft/pkg/cataloger/kernel/package.go index 28e9d6a99..f54a03d28 100644 --- a/syft/pkg/cataloger/kernel/package.go +++ b/syft/pkg/cataloger/kernel/package.go @@ -26,13 +26,14 @@ func createLinuxKernelCPEs(version string) []cpe.CPE { func newLinuxKernelPackage(metadata pkg.LinuxKernel, archiveLocation file.Location) pkg.Package { p := pkg.Package{ - Name: linuxKernelPackageName, - Version: metadata.Version, - Locations: file.NewLocationSet(archiveLocation.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), - PURL: packageURL(linuxKernelPackageName, metadata.Version), - Type: pkg.LinuxKernelPkg, - Metadata: metadata, - CPEs: createLinuxKernelCPEs(metadata.Version), + Name: linuxKernelPackageName, + Version: metadata.Version, + Locations: file.NewLocationSet(archiveLocation.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), + PURL: packageURL(linuxKernelPackageName, metadata.Version), + Type: pkg.LinuxKernelPkg, + Metadata: metadata, + Dependencies: pkg.IncompleteDependencies, + CPEs: createLinuxKernelCPEs(metadata.Version), } p.SetID() @@ -42,13 +43,14 @@ func newLinuxKernelPackage(metadata pkg.LinuxKernel, archiveLocation file.Locati func newLinuxKernelModulePackage(metadata pkg.LinuxKernelModule, kmLocation file.Location) pkg.Package { p := pkg.Package{ - Name: metadata.Name, - Version: metadata.Version, - Locations: file.NewLocationSet(kmLocation.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), - Licenses: pkg.NewLicenseSet(pkg.NewLicensesFromLocation(kmLocation, metadata.License)...), - PURL: packageURL(metadata.Name, metadata.Version), - Type: pkg.LinuxKernelModulePkg, - Metadata: metadata, + Name: metadata.Name, + Version: metadata.Version, + Locations: file.NewLocationSet(kmLocation.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), + Licenses: pkg.NewLicenseSet(pkg.NewLicensesFromLocation(kmLocation, metadata.License)...), + PURL: packageURL(metadata.Name, metadata.Version), + Type: pkg.LinuxKernelModulePkg, + Dependencies: pkg.IncompleteDependencies, + Metadata: metadata, } p.SetID() diff --git a/syft/pkg/cataloger/lua/package.go b/syft/pkg/cataloger/lua/package.go index c9eaa4da9..74abb8982 100644 --- a/syft/pkg/cataloger/lua/package.go +++ b/syft/pkg/cataloger/lua/package.go @@ -16,6 +16,8 @@ func newLuaRocksPackage(u luaRocksPackage, indexLocation file.Location) pkg.Pack Language: pkg.Lua, Licenses: pkg.NewLicenseSet(license...), Type: pkg.LuaRocksPkg, + // no attempt is made by the parser function to raise up dependency relationships + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.LuaRocksPackage{ Name: u.Name, Version: u.Version, diff --git a/syft/pkg/cataloger/lua/parse_rockspec_test.go b/syft/pkg/cataloger/lua/parse_rockspec_test.go index a85cda58c..d5a19eabe 100644 --- a/syft/pkg/cataloger/lua/parse_rockspec_test.go +++ b/syft/pkg/cataloger/lua/parse_rockspec_test.go @@ -24,6 +24,7 @@ func TestParseRockspec(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("Apache-2.0", file.NewLocation("test-fixtures/rockspec/kong-3.7.0-0.rockspec")), ), + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.LuaRocksPackage{ Name: "kong", Version: "3.7.0-0", @@ -45,6 +46,7 @@ func TestParseRockspec(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("MIT/X11", file.NewLocation("test-fixtures/rockspec/lpeg-1.0.2-1.rockspec")), ), + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.LuaRocksPackage{ Name: "LPeg", Version: "1.0.2-1", @@ -66,6 +68,7 @@ func TestParseRockspec(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("MIT", file.NewLocation("test-fixtures/rockspec/kong-pgmoon-1.16.2-1.rockspec")), ), + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.LuaRocksPackage{ Name: "kong-pgmoon", Version: "1.16.2-1", @@ -87,6 +90,7 @@ func TestParseRockspec(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("MIT/X11", file.NewLocation("test-fixtures/rockspec/luasyslog-2.0.1-1.rockspec")), ), + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.LuaRocksPackage{ Name: "luasyslog", Version: "2.0.1-1", diff --git a/syft/pkg/cataloger/nix/cataloger_test.go b/syft/pkg/cataloger/nix/cataloger_test.go index ff929b9f8..8a68db0ba 100644 --- a/syft/pkg/cataloger/nix/cataloger_test.go +++ b/syft/pkg/cataloger/nix/cataloger_test.go @@ -20,12 +20,13 @@ func TestCataloger_Catalog(t *testing.T) { fixture: "test-fixtures/fixture-1", wantPkgs: []pkg.Package{ { - Name: "glibc", - Version: "2.34-210", - PURL: "pkg:nix/glibc@2.34-210?output=bin&outputhash=h0cnbmfcn93xm5dg2x27ixhag1cwndga", - Locations: file.NewLocationSet(file.NewLocation("nix/store/h0cnbmfcn93xm5dg2x27ixhag1cwndga-glibc-2.34-210-bin")), - FoundBy: catalogerName, - Type: pkg.NixPkg, + Name: "glibc", + Version: "2.34-210", + PURL: "pkg:nix/glibc@2.34-210?output=bin&outputhash=h0cnbmfcn93xm5dg2x27ixhag1cwndga", + Locations: file.NewLocationSet(file.NewLocation("nix/store/h0cnbmfcn93xm5dg2x27ixhag1cwndga-glibc-2.34-210-bin")), + FoundBy: catalogerName, + Type: pkg.NixPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.NixStoreEntry{ OutputHash: "h0cnbmfcn93xm5dg2x27ixhag1cwndga", Output: "bin", diff --git a/syft/pkg/cataloger/nix/package.go b/syft/pkg/cataloger/nix/package.go index 56f8acfa9..bad6eb59b 100644 --- a/syft/pkg/cataloger/nix/package.go +++ b/syft/pkg/cataloger/nix/package.go @@ -14,6 +14,8 @@ func newNixStorePackage(storePath nixStorePath, locations ...file.Location) pkg. Locations: file.NewLocationSet(locations...), Type: pkg.NixPkg, PURL: packageURL(storePath), + // no attempt is made by the parser function to raise up dependency relationships + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.NixStoreEntry{ OutputHash: storePath.outputHash, Output: storePath.output, diff --git a/syft/pkg/cataloger/ocaml/package.go b/syft/pkg/cataloger/ocaml/package.go index 5144add41..3e95f20fd 100644 --- a/syft/pkg/cataloger/ocaml/package.go +++ b/syft/pkg/cataloger/ocaml/package.go @@ -15,7 +15,9 @@ func newOpamPackage(m pkg.OpamPackage, fileLocation file.Location) pkg.Package { Locations: file.NewLocationSet(fileLocation), Type: pkg.OpamPkg, Language: pkg.OCaml, - Metadata: m, + // no attempt is made by the parser function to raise up dependency relationships + Dependencies: pkg.IncompleteDependencies, + Metadata: m, } p.SetID() diff --git a/syft/pkg/cataloger/ocaml/parse_opam_test.go b/syft/pkg/cataloger/ocaml/parse_opam_test.go index 63b5fc9d3..ac50ba00c 100644 --- a/syft/pkg/cataloger/ocaml/parse_opam_test.go +++ b/syft/pkg/cataloger/ocaml/parse_opam_test.go @@ -36,8 +36,9 @@ func TestParseOpamPackage(t *testing.T) { "LGPL-2.1-or-later WITH OCaml-LGPL-linking-exception", )..., ), - Language: pkg.OCaml, - Type: pkg.OpamPkg, + Language: pkg.OCaml, + Type: pkg.OpamPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.OpamPackage{ Name: "ocaml-base-compiler", Version: "4.14.0", @@ -65,8 +66,9 @@ func TestParseOpamPackage(t *testing.T) { "ISC", )..., ), - Language: pkg.OCaml, - Type: pkg.OpamPkg, + Language: pkg.OCaml, + Type: pkg.OpamPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.OpamPackage{ Name: "alcotest", Version: "1.5.0", diff --git a/syft/pkg/cataloger/php/package.go b/syft/pkg/cataloger/php/package.go index f35960373..bf5d93d29 100644 --- a/syft/pkg/cataloger/php/package.go +++ b/syft/pkg/cataloger/php/package.go @@ -17,7 +17,9 @@ func newComposerLockPackage(pd parsedLockData, indexLocation file.Location) pkg. PURL: packageURL(pd.Name, pd.Version), Language: pkg.PHP, Type: pkg.PhpComposerPkg, - Metadata: pd.PhpComposerLockEntry, + // no attempt is made by the parser function to raise up dependency relationships + Dependencies: pkg.IncompleteDependencies, + Metadata: pd.PhpComposerLockEntry, } p.SetID() @@ -33,7 +35,9 @@ func newComposerInstalledPackage(pd parsedInstalledData, indexLocation file.Loca PURL: packageURL(pd.Name, pd.Version), Language: pkg.PHP, Type: pkg.PhpComposerPkg, - Metadata: pd.PhpComposerInstalledEntry, + // no attempt is made by the parser function to raise up dependency relationships + Dependencies: pkg.IncompleteDependencies, + Metadata: pd.PhpComposerInstalledEntry, } p.SetID() @@ -49,7 +53,9 @@ func newPeclPackage(pd pkg.PhpPeclEntry, indexLocation file.Location) pkg.Packag PURL: packageURLFromPecl(pd.Name, pd.Version), Language: pkg.PHP, Type: pkg.PhpPeclPkg, - Metadata: pd, + // no attempt is made by the parser function to raise up dependency relationships + Dependencies: pkg.IncompleteDependencies, + Metadata: pd, } p.SetID() diff --git a/syft/pkg/cataloger/php/parse_composer_lock_test.go b/syft/pkg/cataloger/php/parse_composer_lock_test.go index 1da97c42d..2985f8e9f 100644 --- a/syft/pkg/cataloger/php/parse_composer_lock_test.go +++ b/syft/pkg/cataloger/php/parse_composer_lock_test.go @@ -22,8 +22,9 @@ func TestParseComposerFileLock(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("MIT", file.NewLocation(fixture)), ), - Language: pkg.PHP, - Type: pkg.PhpComposerPkg, + Language: pkg.PHP, + Type: pkg.PhpComposerPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.PhpComposerLockEntry{ Name: "adoy/fastcgi-client", Version: "1.0.2", @@ -62,7 +63,8 @@ func TestParseComposerFileLock(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("MIT", file.NewLocation(fixture)), ), - Type: pkg.PhpComposerPkg, + Type: pkg.PhpComposerPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.PhpComposerLockEntry{ Name: "alcaeus/mongo-php-adapter", Version: "1.1.11", diff --git a/syft/pkg/cataloger/php/parse_installed_json_test.go b/syft/pkg/cataloger/php/parse_installed_json_test.go index 7e0c06c32..97aed15d9 100644 --- a/syft/pkg/cataloger/php/parse_installed_json_test.go +++ b/syft/pkg/cataloger/php/parse_installed_json_test.go @@ -26,6 +26,7 @@ func TestParseInstalledJsonComposerV1(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicense("MIT"), ), + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.PhpComposerInstalledEntry{ Name: "asm89/stack-cors", Version: "1.3.0", @@ -75,6 +76,7 @@ func TestParseInstalledJsonComposerV1(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicense("MIT"), ), + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.PhpComposerInstalledEntry{ Name: "behat/mink", Version: "v1.8.1", diff --git a/syft/pkg/cataloger/php/parse_pecl_serialized_test.go b/syft/pkg/cataloger/php/parse_pecl_serialized_test.go index 84f84ea72..40d73174d 100644 --- a/syft/pkg/cataloger/php/parse_pecl_serialized_test.go +++ b/syft/pkg/cataloger/php/parse_pecl_serialized_test.go @@ -22,8 +22,9 @@ func TestParsePeclSerialized(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("PHP License", file.NewLocation(fixture)), ), - Language: pkg.PHP, - Type: pkg.PhpPeclPkg, + Language: pkg.PHP, + Type: pkg.PhpPeclPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.PhpPeclEntry{ Name: "memcached", Version: "3.2.0", diff --git a/syft/pkg/cataloger/python/cataloger_test.go b/syft/pkg/cataloger/python/cataloger_test.go index 8e827322e..5d508b012 100644 --- a/syft/pkg/cataloger/python/cataloger_test.go +++ b/syft/pkg/cataloger/python/cataloger_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/require" + "github.com/anchore/syft/internal/licenses" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest" @@ -23,11 +24,12 @@ func Test_PackageCataloger(t *testing.T) { name: "egg-file-no-version", fixtures: []string{"test-fixtures/no-version-py3.8.egg-info"}, expectedPackage: pkg.Package{ - Name: "no-version", - PURL: "pkg:pypi/no-version", - Type: pkg.PythonPkg, - Language: pkg.Python, - FoundBy: "python-installed-package-cataloger", + Name: "no-version", + PURL: "pkg:pypi/no-version", + Type: pkg.PythonPkg, + Language: pkg.Python, + FoundBy: "python-installed-package-cataloger", + Dependencies: pkg.CompleteDependencies, Metadata: pkg.PythonPackage{ Name: "no-version", SitePackagesRootPath: "test-fixtures", @@ -50,7 +52,8 @@ func Test_PackageCataloger(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("Apache 2.0", file.NewLocation("test-fixtures/egg-info/PKG-INFO")), ), - FoundBy: "python-installed-package-cataloger", + FoundBy: "python-installed-package-cataloger", + Dependencies: pkg.CompleteDependencies, Metadata: pkg.PythonPackage{ Name: "requests", Version: "2.22.0", @@ -88,7 +91,8 @@ func Test_PackageCataloger(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("Apache 2.0", file.NewLocation("test-fixtures/casesensitive/EGG-INFO/PKG-INFO")), ), - FoundBy: "python-installed-package-cataloger", + FoundBy: "python-installed-package-cataloger", + Dependencies: pkg.CompleteDependencies, Metadata: pkg.PythonPackage{ Name: "requests", Version: "2.22.0", @@ -127,7 +131,8 @@ func Test_PackageCataloger(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("BSD License", file.NewLocation("test-fixtures/dist-info/METADATA")), ), - FoundBy: "python-installed-package-cataloger", + FoundBy: "python-installed-package-cataloger", + Dependencies: pkg.CompleteDependencies, Metadata: pkg.PythonPackage{ Name: "Pygments", Version: "2.6.1", @@ -169,7 +174,8 @@ func Test_PackageCataloger(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("BSD License", file.NewLocation("test-fixtures/casesensitive/DIST-INFO/METADATA")), ), - FoundBy: "python-installed-package-cataloger", + FoundBy: "python-installed-package-cataloger", + Dependencies: pkg.CompleteDependencies, Metadata: pkg.PythonPackage{ Name: "Pygments", Version: "2.6.1", @@ -207,7 +213,8 @@ func Test_PackageCataloger(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("BSD License", file.NewLocation("test-fixtures/malformed-record/dist-info/METADATA")), ), - FoundBy: "python-installed-package-cataloger", + FoundBy: "python-installed-package-cataloger", + Dependencies: pkg.CompleteDependencies, Metadata: pkg.PythonPackage{ Name: "Pygments", Version: "2.6.1", @@ -239,7 +246,8 @@ func Test_PackageCataloger(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("BSD License", file.NewLocation("test-fixtures/partial.dist-info/METADATA")), ), - FoundBy: "python-installed-package-cataloger", + FoundBy: "python-installed-package-cataloger", + Dependencies: pkg.CompleteDependencies, Metadata: pkg.PythonPackage{ Name: "Pygments", Version: "2.6.1", @@ -263,7 +271,8 @@ func Test_PackageCataloger(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("Apache 2.0", file.NewLocation("test-fixtures/test.egg-info")), ), - FoundBy: "python-installed-package-cataloger", + FoundBy: "python-installed-package-cataloger", + Dependencies: pkg.CompleteDependencies, Metadata: pkg.PythonPackage{ Name: "requests", Version: "2.22.0", @@ -278,6 +287,8 @@ func Test_PackageCataloger(t *testing.T) { }, } + ctx := licenses.SetContextLicenseScanner(context.Background(), licenses.NewDefaultScanner()) + for _, test := range tests { t.Run(test.name, func(t *testing.T) { resolver := file.NewMockResolverForPaths(test.fixtures...) @@ -289,6 +300,7 @@ func Test_PackageCataloger(t *testing.T) { pkgtest.NewCatalogTester(). WithResolver(resolver). + WithContext(ctx). Expects([]pkg.Package{test.expectedPackage}, nil). TestCataloger(t, NewInstalledPackageCataloger()) }) @@ -296,6 +308,8 @@ func Test_PackageCataloger(t *testing.T) { } func Test_PackageCataloger_IgnorePackage(t *testing.T) { + ctx := licenses.SetContextLicenseScanner(context.Background(), licenses.NewDefaultScanner()) + tests := []struct { MetadataFixture string }{ @@ -311,7 +325,7 @@ func Test_PackageCataloger_IgnorePackage(t *testing.T) { t.Run(test.MetadataFixture, func(t *testing.T) { resolver := file.NewMockResolverForPaths(test.MetadataFixture) - actual, _, err := NewInstalledPackageCataloger().Catalog(context.Background(), resolver) + actual, _, err := NewInstalledPackageCataloger().Catalog(ctx, resolver) require.NoError(t, err) if len(actual) != 0 { @@ -353,6 +367,7 @@ func Test_IndexCataloger_Globs(t *testing.T) { } func Test_PackageCataloger_Globs(t *testing.T) { + ctx := licenses.SetContextLicenseScanner(context.Background(), licenses.NewDefaultScanner()) tests := []struct { name string fixture string @@ -375,6 +390,7 @@ func Test_PackageCataloger_Globs(t *testing.T) { t.Run(test.name, func(t *testing.T) { pkgtest.NewCatalogTester(). FromDirectory(t, test.fixture). + WithContext(ctx). ExpectsResolverContentQueries(test.expected). IgnoreUnfulfilledPathResponses("**/pyvenv.cfg"). TestCataloger(t, NewInstalledPackageCataloger()) @@ -670,10 +686,13 @@ func Test_PackageCataloger_SitePackageRelationships(t *testing.T) { }, } + ctx := licenses.SetContextLicenseScanner(context.Background(), licenses.NewDefaultScanner()) + for _, test := range tests { t.Run(test.name, func(t *testing.T) { pkgtest.NewCatalogTester(). WithImageResolver(t, test.fixture). + WithContext(ctx). WithPackageStringer(stringPackage). ExpectsRelationshipStrings(test.expectedRelationships). TestCataloger(t, NewInstalledPackageCataloger()) diff --git a/syft/pkg/cataloger/python/package.go b/syft/pkg/cataloger/python/package.go index e7c861256..79f0672e1 100644 --- a/syft/pkg/cataloger/python/package.go +++ b/syft/pkg/cataloger/python/package.go @@ -20,16 +20,17 @@ func normalize(name string) string { return strings.ToLower(normalized) } -func newPackageForIndex(name, version string, locations ...file.Location) pkg.Package { +func newPackageForIndex(name, version string, dep pkg.DependencyCompleteness, locations ...file.Location) pkg.Package { name = normalize(name) p := pkg.Package{ - Name: name, - Version: version, - Locations: file.NewLocationSet(locations...), - PURL: packageURL(name, version, nil), - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: name, + Version: version, + Locations: file.NewLocationSet(locations...), + PURL: packageURL(name, version, nil), + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: dep, } p.SetID() @@ -37,17 +38,18 @@ func newPackageForIndex(name, version string, locations ...file.Location) pkg.Pa return p } -func newPackageForIndexWithMetadata(name, version string, metadata interface{}, locations ...file.Location) pkg.Package { +func newPackageForIndexWithMetadata(name, version string, metadata interface{}, dep pkg.DependencyCompleteness, locations ...file.Location) pkg.Package { name = normalize(name) p := pkg.Package{ - Name: name, - Version: version, - Locations: file.NewLocationSet(locations...), - PURL: packageURL(name, version, nil), - Language: pkg.Python, - Type: pkg.PythonPkg, - Metadata: metadata, + Name: name, + Version: version, + Locations: file.NewLocationSet(locations...), + PURL: packageURL(name, version, nil), + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: dep, + Metadata: metadata, } p.SetID() @@ -55,17 +57,18 @@ func newPackageForIndexWithMetadata(name, version string, metadata interface{}, return p } -func newPackageForRequirementsWithMetadata(name, version string, metadata pkg.PythonRequirementsEntry, locations ...file.Location) pkg.Package { +func newPackageForRequirementsWithMetadata(name, version string, metadata pkg.PythonRequirementsEntry, dep pkg.DependencyCompleteness, locations ...file.Location) pkg.Package { name = normalize(name) p := pkg.Package{ - Name: name, - Version: version, - Locations: file.NewLocationSet(locations...), - PURL: packageURL(name, version, nil), - Language: pkg.Python, - Type: pkg.PythonPkg, - Metadata: metadata, + Name: name, + Version: version, + Locations: file.NewLocationSet(locations...), + PURL: packageURL(name, version, nil), + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: dep, + Metadata: metadata, } p.SetID() @@ -73,18 +76,19 @@ func newPackageForRequirementsWithMetadata(name, version string, metadata pkg.Py return p } -func newPackageForPackage(m parsedData, licenses pkg.LicenseSet, sources ...file.Location) pkg.Package { +func newPackageForPackage(m parsedData, licenses pkg.LicenseSet, dep pkg.DependencyCompleteness, sources ...file.Location) pkg.Package { name := normalize(m.Name) p := pkg.Package{ - Name: name, - Version: m.Version, - PURL: packageURL(name, m.Version, &m.PythonPackage), - Locations: file.NewLocationSet(sources...), - Licenses: licenses, - Language: pkg.Python, - Type: pkg.PythonPkg, - Metadata: m.PythonPackage, + Name: name, + Version: m.Version, + PURL: packageURL(name, m.Version, &m.PythonPackage), + Locations: file.NewLocationSet(sources...), + Licenses: licenses, + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: dep, + Metadata: m.PythonPackage, } p.SetID() diff --git a/syft/pkg/cataloger/python/parse_pipfile_lock.go b/syft/pkg/cataloger/python/parse_pipfile_lock.go index b2100060a..f6398a8c4 100644 --- a/syft/pkg/cataloger/python/parse_pipfile_lock.go +++ b/syft/pkg/cataloger/python/parse_pipfile_lock.go @@ -66,7 +66,13 @@ func parsePipfileLock(_ context.Context, _ file.Resolver, _ *generic.Environment index = "https://pypi.org/simple" } version := strings.TrimPrefix(pkgMeta.Version, "==") - pkgs = append(pkgs, newPackageForIndexWithMetadata(name, version, pkg.PythonPipfileLockEntry{Index: index, Hashes: pkgMeta.Hashes}, reader.Location)) + pkgs = append(pkgs, newPackageForIndexWithMetadata( + name, + version, + pkg.PythonPipfileLockEntry{Index: index, Hashes: pkgMeta.Hashes}, + pkg.IncompleteDependencies, // no attempt is made to resolve dependencies from the lock file + reader.Location, + )) } } diff --git a/syft/pkg/cataloger/python/parse_pipfile_lock_test.go b/syft/pkg/cataloger/python/parse_pipfile_lock_test.go index 051bfd78a..c682ef253 100644 --- a/syft/pkg/cataloger/python/parse_pipfile_lock_test.go +++ b/syft/pkg/cataloger/python/parse_pipfile_lock_test.go @@ -15,12 +15,13 @@ func TestParsePipFileLock(t *testing.T) { locations := file.NewLocationSet(file.NewLocation(fixture)) expectedPkgs := []pkg.Package{ { - Name: "aio-pika", - Version: "6.8.0", - PURL: "pkg:pypi/aio-pika@6.8.0", - Locations: locations, - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: "aio-pika", + Version: "6.8.0", + PURL: "pkg:pypi/aio-pika@6.8.0", + Locations: locations, + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.PythonPipfileLockEntry{ Index: "https://pypi.org/simple", Hashes: []string{ @@ -29,12 +30,13 @@ func TestParsePipFileLock(t *testing.T) { }}, }, { - Name: "aiodns", - Version: "2.0.0", - PURL: "pkg:pypi/aiodns@2.0.0", - Locations: locations, - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: "aiodns", + Version: "2.0.0", + PURL: "pkg:pypi/aiodns@2.0.0", + Locations: locations, + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.PythonPipfileLockEntry{ Index: "https://test.pypi.org/simple", Hashes: []string{ @@ -44,12 +46,13 @@ func TestParsePipFileLock(t *testing.T) { }, }, { - Name: "aiohttp", - Version: "3.7.4.post0", - PURL: "pkg:pypi/aiohttp@3.7.4.post0", - Locations: locations, - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: "aiohttp", + Version: "3.7.4.post0", + PURL: "pkg:pypi/aiohttp@3.7.4.post0", + Locations: locations, + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.PythonPipfileLockEntry{ Index: "https://pypi.org/simple", Hashes: []string{ @@ -59,12 +62,13 @@ func TestParsePipFileLock(t *testing.T) { }, }, { - Name: "aiohttp-jinja2", - Version: "1.4.2", - PURL: "pkg:pypi/aiohttp-jinja2@1.4.2", - Locations: locations, - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: "aiohttp-jinja2", + Version: "1.4.2", + PURL: "pkg:pypi/aiohttp-jinja2@1.4.2", + Locations: locations, + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.PythonPipfileLockEntry{ Index: "https://pypi.org/simple", Hashes: []string{ diff --git a/syft/pkg/cataloger/python/parse_poetry_lock.go b/syft/pkg/cataloger/python/parse_poetry_lock.go index 2b75f51b8..10ea43980 100644 --- a/syft/pkg/cataloger/python/parse_poetry_lock.go +++ b/syft/pkg/cataloger/python/parse_poetry_lock.go @@ -99,6 +99,7 @@ func poetryLockPackages(reader file.LocationReadCloser) ([]pkg.Package, error) { p.Name, p.Version, newPythonPoetryLockEntry(p), + pkg.CompleteDependencies, reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), ) diff --git a/syft/pkg/cataloger/python/parse_poetry_lock_test.go b/syft/pkg/cataloger/python/parse_poetry_lock_test.go index 0cb0030a2..533a3a77d 100644 --- a/syft/pkg/cataloger/python/parse_poetry_lock_test.go +++ b/syft/pkg/cataloger/python/parse_poetry_lock_test.go @@ -14,12 +14,13 @@ func TestParsePoetryLock(t *testing.T) { locations := file.NewLocationSet(file.NewLocation(fixture)) expectedPkgs := []pkg.Package{ { - Name: "added-value", - Version: "0.14.2", - PURL: "pkg:pypi/added-value@0.14.2", - Locations: locations, - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: "added-value", + Version: "0.14.2", + PURL: "pkg:pypi/added-value@0.14.2", + Locations: locations, + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.PythonPoetryLockEntry{ Index: "https://test.pypi.org/simple", Dependencies: []pkg.PythonPoetryLockDependencyEntry{ @@ -49,31 +50,34 @@ func TestParsePoetryLock(t *testing.T) { }, }, { - Name: "alabaster", - Version: "0.7.12", - PURL: "pkg:pypi/alabaster@0.7.12", - Locations: locations, - Language: pkg.Python, - Type: pkg.PythonPkg, - Metadata: pkg.PythonPoetryLockEntry{Index: "https://pypi.org/simple"}, + Name: "alabaster", + Version: "0.7.12", + PURL: "pkg:pypi/alabaster@0.7.12", + Locations: locations, + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.CompleteDependencies, + Metadata: pkg.PythonPoetryLockEntry{Index: "https://pypi.org/simple"}, }, { - Name: "appnope", - Version: "0.1.0", - PURL: "pkg:pypi/appnope@0.1.0", - Locations: locations, - Language: pkg.Python, - Type: pkg.PythonPkg, - Metadata: pkg.PythonPoetryLockEntry{Index: "https://pypi.org/simple"}, + Name: "appnope", + Version: "0.1.0", + PURL: "pkg:pypi/appnope@0.1.0", + Locations: locations, + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.CompleteDependencies, + Metadata: pkg.PythonPoetryLockEntry{Index: "https://pypi.org/simple"}, }, { - Name: "asciitree", - Version: "0.3.3", - PURL: "pkg:pypi/asciitree@0.3.3", - Locations: locations, - Language: pkg.Python, - Type: pkg.PythonPkg, - Metadata: pkg.PythonPoetryLockEntry{Index: "https://pypi.org/simple"}, + Name: "asciitree", + Version: "0.3.3", + PURL: "pkg:pypi/asciitree@0.3.3", + Locations: locations, + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.CompleteDependencies, + Metadata: pkg.PythonPoetryLockEntry{Index: "https://pypi.org/simple"}, }, } diff --git a/syft/pkg/cataloger/python/parse_requirements.go b/syft/pkg/cataloger/python/parse_requirements.go index 7d5d1d8a4..90a2e86d1 100644 --- a/syft/pkg/cataloger/python/parse_requirements.go +++ b/syft/pkg/cataloger/python/parse_requirements.go @@ -153,6 +153,7 @@ func (rp requirementsParser) parseRequirementsTxt(_ context.Context, _ file.Reso URL: parseURL(req.URL), Markers: req.Markers, }, + pkg.IncompleteDependencies, // not attempt is made by the parser function to resolve dependencies reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), ) diff --git a/syft/pkg/cataloger/python/parse_requirements_test.go b/syft/pkg/cataloger/python/parse_requirements_test.go index 6573b13d6..f34e85876 100644 --- a/syft/pkg/cataloger/python/parse_requirements_test.go +++ b/syft/pkg/cataloger/python/parse_requirements_test.go @@ -17,36 +17,39 @@ func TestParseRequirementsTxt(t *testing.T) { pinnedPkgs := []pkg.Package{ { - Name: "flask", - Version: "4.0.0", - PURL: "pkg:pypi/flask@4.0.0", - Locations: locations, - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: "flask", + Version: "4.0.0", + PURL: "pkg:pypi/flask@4.0.0", + Locations: locations, + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.PythonRequirementsEntry{ Name: "flask", VersionConstraint: "== 4.0.0", }, }, { - Name: "foo", - Version: "1.0.0", - PURL: "pkg:pypi/foo@1.0.0", - Locations: locations, - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: "foo", + Version: "1.0.0", + PURL: "pkg:pypi/foo@1.0.0", + Locations: locations, + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.PythonRequirementsEntry{ Name: "foo", VersionConstraint: "== 1.0.0", }, }, { - Name: "someproject", - Version: "5.4", - PURL: "pkg:pypi/someproject@5.4", - Locations: locations, - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: "someproject", + Version: "5.4", + PURL: "pkg:pypi/someproject@5.4", + Locations: locations, + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.PythonRequirementsEntry{ Name: "SomeProject", VersionConstraint: "==5.4", @@ -54,48 +57,52 @@ func TestParseRequirementsTxt(t *testing.T) { }, }, { - Name: "dots-allowed", - Version: "1.0.0", - PURL: "pkg:pypi/dots-allowed@1.0.0", - Locations: locations, - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: "dots-allowed", + Version: "1.0.0", + PURL: "pkg:pypi/dots-allowed@1.0.0", + Locations: locations, + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.PythonRequirementsEntry{ Name: "dots-._allowed", VersionConstraint: "== 1.0.0", }, }, { - Name: "argh", - Version: "0.26.2", - PURL: "pkg:pypi/argh@0.26.2", - Locations: locations, - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: "argh", + Version: "0.26.2", + PURL: "pkg:pypi/argh@0.26.2", + Locations: locations, + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.PythonRequirementsEntry{ Name: "argh", VersionConstraint: "==0.26.2", }, }, { - Name: "argh", - Version: "0.26.3", - PURL: "pkg:pypi/argh@0.26.3", - Locations: locations, - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: "argh", + Version: "0.26.3", + PURL: "pkg:pypi/argh@0.26.3", + Locations: locations, + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.PythonRequirementsEntry{ Name: "argh", VersionConstraint: "==0.26.3", }, }, { - Name: "celery", - Version: "4.4.7", - PURL: "pkg:pypi/celery@4.4.7", - Locations: locations, - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: "celery", + Version: "4.4.7", + PURL: "pkg:pypi/celery@4.4.7", + Locations: locations, + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.PythonRequirementsEntry{ Name: "celery", Extras: []string{"redis", "pytest"}, @@ -103,12 +110,13 @@ func TestParseRequirementsTxt(t *testing.T) { }, }, { - Name: "githubsampleproject", - Version: "3.7.1", - PURL: "pkg:pypi/githubsampleproject@3.7.1", - Locations: locations, - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: "githubsampleproject", + Version: "3.7.1", + PURL: "pkg:pypi/githubsampleproject@3.7.1", + Locations: locations, + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.PythonRequirementsEntry{ Name: "GithubSampleProject", VersionConstraint: "== 3.7.1", @@ -116,12 +124,13 @@ func TestParseRequirementsTxt(t *testing.T) { }, }, { - Name: "friendly-bard", - Version: "1.0.0", - PURL: "pkg:pypi/friendly-bard@1.0.0", - Locations: locations, - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: "friendly-bard", + Version: "1.0.0", + PURL: "pkg:pypi/friendly-bard@1.0.0", + Locations: locations, + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.PythonRequirementsEntry{ Name: "FrIeNdLy-_-bArD", VersionConstraint: "== 1.0.0", @@ -152,48 +161,52 @@ func TestParseRequirementsTxt(t *testing.T) { }, expectedPkgs: append([]pkg.Package{ { - Name: "mopidy-dirble", - Version: "1.1", - PURL: "pkg:pypi/mopidy-dirble@1.1", - Locations: locations, - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: "mopidy-dirble", + Version: "1.1", + PURL: "pkg:pypi/mopidy-dirble@1.1", + Locations: locations, + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.PythonRequirementsEntry{ Name: "Mopidy-Dirble", VersionConstraint: "~= 1.1", }, }, { - Name: "sqlalchemy", - Version: "2.0.0", - PURL: "pkg:pypi/sqlalchemy@2.0.0", - Locations: locations, - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: "sqlalchemy", + Version: "2.0.0", + PURL: "pkg:pypi/sqlalchemy@2.0.0", + Locations: locations, + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.PythonRequirementsEntry{ Name: "sqlalchemy", VersionConstraint: ">= 1.0.0, <= 2.0.0, != 3.0.0, <= 3.0.0", }, }, { - Name: "bar", - Version: "2.0.0", - PURL: "pkg:pypi/bar@2.0.0", - Locations: locations, - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: "bar", + Version: "2.0.0", + PURL: "pkg:pypi/bar@2.0.0", + Locations: locations, + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.PythonRequirementsEntry{ Name: "bar", VersionConstraint: ">= 1.0.0, <= 2.0.0, != 3.0.0, <= 3.0.0", }, }, { - Name: "numpy", - Version: "3.4.1", - PURL: "pkg:pypi/numpy@3.4.1", - Locations: locations, - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: "numpy", + Version: "3.4.1", + PURL: "pkg:pypi/numpy@3.4.1", + Locations: locations, + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.PythonRequirementsEntry{ Name: "numpy", VersionConstraint: ">= 3.4.1", @@ -201,12 +214,13 @@ func TestParseRequirementsTxt(t *testing.T) { }, }, { - Name: "requests", - Version: "2.8.0", - PURL: "pkg:pypi/requests@2.8.0", - Locations: locations, - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: "requests", + Version: "2.8.0", + PURL: "pkg:pypi/requests@2.8.0", + Locations: locations, + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.PythonRequirementsEntry{ Name: "requests", Extras: []string{"security"}, diff --git a/syft/pkg/cataloger/python/parse_setup.go b/syft/pkg/cataloger/python/parse_setup.go index ccbe916f5..21577b9e8 100644 --- a/syft/pkg/cataloger/python/parse_setup.go +++ b/syft/pkg/cataloger/python/parse_setup.go @@ -59,6 +59,7 @@ func parseSetup(_ context.Context, _ file.Resolver, _ *generic.Environment, read newPackageForIndex( name, version, + pkg.IncompleteDependencies, // no attempt is made by the parser function to resolve dependencies reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), ) diff --git a/syft/pkg/cataloger/python/parse_setup_test.go b/syft/pkg/cataloger/python/parse_setup_test.go index 665007296..4130616b4 100644 --- a/syft/pkg/cataloger/python/parse_setup_test.go +++ b/syft/pkg/cataloger/python/parse_setup_test.go @@ -20,39 +20,44 @@ func TestParseSetup(t *testing.T) { fixture: "test-fixtures/setup/setup.py", expected: []pkg.Package{ { - Name: "pathlib3", - Version: "2.2.0", - PURL: "pkg:pypi/pathlib3@2.2.0", - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: "pathlib3", + Version: "2.2.0", + PURL: "pkg:pypi/pathlib3@2.2.0", + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.IncompleteDependencies, }, { - Name: "mypy", - Version: "v0.770", - PURL: "pkg:pypi/mypy@v0.770", - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: "mypy", + Version: "v0.770", + PURL: "pkg:pypi/mypy@v0.770", + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.IncompleteDependencies, }, { - Name: "mypy1", - Version: "v0.770", - PURL: "pkg:pypi/mypy1@v0.770", - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: "mypy1", + Version: "v0.770", + PURL: "pkg:pypi/mypy1@v0.770", + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.IncompleteDependencies, }, { - Name: "mypy2", - Version: "v0.770", - PURL: "pkg:pypi/mypy2@v0.770", - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: "mypy2", + Version: "v0.770", + PURL: "pkg:pypi/mypy2@v0.770", + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.IncompleteDependencies, }, { - Name: "mypy3", - Version: "v0.770", - PURL: "pkg:pypi/mypy3@v0.770", - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: "mypy3", + Version: "v0.770", + PURL: "pkg:pypi/mypy3@v0.770", + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.IncompleteDependencies, }, }, }, diff --git a/syft/pkg/cataloger/python/parse_wheel_egg.go b/syft/pkg/cataloger/python/parse_wheel_egg.go index 2d2b9487c..62a7afd70 100644 --- a/syft/pkg/cataloger/python/parse_wheel_egg.go +++ b/syft/pkg/cataloger/python/parse_wheel_egg.go @@ -40,6 +40,7 @@ func parseWheelOrEgg(ctx context.Context, resolver file.Resolver, _ *generic.Env newPackageForPackage( *pd, findLicenses(ctx, licenseScanner, resolver, *pd), + pkg.CompleteDependencies, sources..., ), } diff --git a/syft/pkg/cataloger/r/cataloger_test.go b/syft/pkg/cataloger/r/cataloger_test.go index 18452cf88..4aacdd26d 100644 --- a/syft/pkg/cataloger/r/cataloger_test.go +++ b/syft/pkg/cataloger/r/cataloger_test.go @@ -12,14 +12,15 @@ import ( func TestRPackageCataloger(t *testing.T) { expectedPkgs := []pkg.Package{ { - Name: "base", - Version: "4.3.0", - FoundBy: "r-package-cataloger", - Locations: file.NewLocationSet(file.NewLocation("base/DESCRIPTION")), - Licenses: pkg.NewLicenseSet([]pkg.License{pkg.NewLicense("Part of R 4.3.0")}...), - Language: pkg.R, - Type: pkg.Rpkg, - PURL: "pkg:cran/base@4.3.0", + Name: "base", + Version: "4.3.0", + FoundBy: "r-package-cataloger", + Locations: file.NewLocationSet(file.NewLocation("base/DESCRIPTION")), + Licenses: pkg.NewLicenseSet([]pkg.License{pkg.NewLicense("Part of R 4.3.0")}...), + Language: pkg.R, + Type: pkg.Rpkg, + Dependencies: pkg.IncompleteDependencies, + PURL: "pkg:cran/base@4.3.0", Metadata: pkg.RDescription{ Title: "The R Base Package", Description: "Base R functions.", @@ -30,14 +31,15 @@ func TestRPackageCataloger(t *testing.T) { }, }, { - Name: "stringr", - Version: "1.5.0.9000", - FoundBy: "r-package-cataloger", - Locations: file.NewLocationSet(file.NewLocation("stringr/DESCRIPTION")), - Licenses: pkg.NewLicenseSet([]pkg.License{pkg.NewLicense("MIT")}...), - Language: pkg.R, - Type: pkg.Rpkg, - PURL: "pkg:cran/stringr@1.5.0.9000", + Name: "stringr", + Version: "1.5.0.9000", + FoundBy: "r-package-cataloger", + Locations: file.NewLocationSet(file.NewLocation("stringr/DESCRIPTION")), + Licenses: pkg.NewLicenseSet([]pkg.License{pkg.NewLicense("MIT")}...), + Language: pkg.R, + Type: pkg.Rpkg, + Dependencies: pkg.IncompleteDependencies, + PURL: "pkg:cran/stringr@1.5.0.9000", Metadata: pkg.RDescription{ Title: "Simple, Consistent Wrappers for Common String Operations", Description: "A consistent, simple and easy to use set of wrappers around the fantastic 'stringi' package. All function and argument names (and positions) are consistent, all functions deal with \"NA\"'s and zero length vectors in the same way, and the output from one function is easy to feed into the input of another.", diff --git a/syft/pkg/cataloger/r/package.go b/syft/pkg/cataloger/r/package.go index e5ca3c486..0c603e3ae 100644 --- a/syft/pkg/cataloger/r/package.go +++ b/syft/pkg/cataloger/r/package.go @@ -24,7 +24,9 @@ func newPackage(pd parseData, locations ...file.Location) pkg.Package { Language: pkg.R, Type: pkg.Rpkg, PURL: packageURL(pd), - Metadata: pd.RDescription, + // no attempt is made by the parser function to resolve dependencies + Dependencies: pkg.IncompleteDependencies, + Metadata: pd.RDescription, } result.SetID() diff --git a/syft/pkg/cataloger/redhat/cataloger_test.go b/syft/pkg/cataloger/redhat/cataloger_test.go index 5dbb133b1..5f233d7ec 100644 --- a/syft/pkg/cataloger/redhat/cataloger_test.go +++ b/syft/pkg/cataloger/redhat/cataloger_test.go @@ -20,13 +20,14 @@ func Test_DBCataloger(t *testing.T) { locations := file.NewLocationSet(dbLocation.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)) basePkg := pkg.Package{ - Name: "basesystem", - Version: "11-13.el9", - Type: pkg.RpmPkg, - Locations: locations, - Licenses: pkg.NewLicenseSet(pkg.NewLicenseFromLocations("Public Domain", dbLocation)), - FoundBy: "rpm-db-cataloger", - PURL: "pkg:rpm/basesystem@11-13.el9?arch=noarch&upstream=basesystem-11-13.el9.src.rpm", + Name: "basesystem", + Version: "11-13.el9", + Type: pkg.RpmPkg, + Locations: locations, + Licenses: pkg.NewLicenseSet(pkg.NewLicenseFromLocations("Public Domain", dbLocation)), + FoundBy: "rpm-db-cataloger", + PURL: "pkg:rpm/basesystem@11-13.el9?arch=noarch&upstream=basesystem-11-13.el9.src.rpm", + Dependencies: pkg.CompleteDependencies, Metadata: pkg.RpmDBEntry{ Name: "basesystem", Version: "11", @@ -50,13 +51,14 @@ func Test_DBCataloger(t *testing.T) { basePkg.SetID() bashPkg := pkg.Package{ - Name: "bash", - Version: "5.1.8-6.el9_1", - Type: pkg.RpmPkg, - Locations: locations, - Licenses: pkg.NewLicenseSet(pkg.NewLicenseFromLocations("GPLv3+", dbLocation)), - FoundBy: "rpm-db-cataloger", - PURL: "pkg:rpm/bash@5.1.8-6.el9_1?arch=x86_64&upstream=bash-5.1.8-6.el9_1.src.rpm", + Name: "bash", + Version: "5.1.8-6.el9_1", + Type: pkg.RpmPkg, + Locations: locations, + Licenses: pkg.NewLicenseSet(pkg.NewLicenseFromLocations("GPLv3+", dbLocation)), + FoundBy: "rpm-db-cataloger", + PURL: "pkg:rpm/bash@5.1.8-6.el9_1?arch=x86_64&upstream=bash-5.1.8-6.el9_1.src.rpm", + Dependencies: pkg.CompleteDependencies, Metadata: pkg.RpmDBEntry{ Name: "bash", Version: "5.1.8", @@ -102,13 +104,14 @@ func Test_DBCataloger(t *testing.T) { bashPkg.SetID() filesystemPkg := pkg.Package{ - Name: "filesystem", - Version: "3.16-2.el9", - Type: pkg.RpmPkg, - Locations: locations, - Licenses: pkg.NewLicenseSet(pkg.NewLicenseFromLocations("Public Domain", dbLocation)), - FoundBy: "rpm-db-cataloger", - PURL: "pkg:rpm/filesystem@3.16-2.el9?arch=x86_64&upstream=filesystem-3.16-2.el9.src.rpm", + Name: "filesystem", + Version: "3.16-2.el9", + Type: pkg.RpmPkg, + Locations: locations, + Licenses: pkg.NewLicenseSet(pkg.NewLicenseFromLocations("Public Domain", dbLocation)), + FoundBy: "rpm-db-cataloger", + PURL: "pkg:rpm/filesystem@3.16-2.el9?arch=x86_64&upstream=filesystem-3.16-2.el9.src.rpm", + Dependencies: pkg.CompleteDependencies, Metadata: pkg.RpmDBEntry{ Name: "filesystem", Version: "3.16", diff --git a/syft/pkg/cataloger/redhat/package.go b/syft/pkg/cataloger/redhat/package.go index 8bbcfe9a0..dd75ba4d7 100644 --- a/syft/pkg/cataloger/redhat/package.go +++ b/syft/pkg/cataloger/redhat/package.go @@ -11,15 +11,16 @@ import ( "github.com/anchore/syft/syft/pkg" ) -func newDBPackage(dbOrRpmLocation file.Location, m pkg.RpmDBEntry, distro *linux.Release, licenses []string) pkg.Package { +func newDBPackage(dbOrRpmLocation file.Location, m pkg.RpmDBEntry, distro *linux.Release, licenses []string, deps pkg.DependencyCompleteness) pkg.Package { p := pkg.Package{ - Name: m.Name, - Version: toELVersion(m.Epoch, m.Version, m.Release), - Licenses: pkg.NewLicenseSet(pkg.NewLicensesFromLocation(dbOrRpmLocation, licenses...)...), - PURL: packageURL(m.Name, m.Arch, m.Epoch, m.SourceRpm, m.Version, m.Release, distro), - Locations: file.NewLocationSet(dbOrRpmLocation.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), - Type: pkg.RpmPkg, - Metadata: m, + Name: m.Name, + Version: toELVersion(m.Epoch, m.Version, m.Release), + Licenses: pkg.NewLicenseSet(pkg.NewLicensesFromLocation(dbOrRpmLocation, licenses...)...), + PURL: packageURL(m.Name, m.Arch, m.Epoch, m.SourceRpm, m.Version, m.Release, distro), + Locations: file.NewLocationSet(dbOrRpmLocation.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), + Type: pkg.RpmPkg, + Dependencies: deps, + Metadata: m, } p.SetID() diff --git a/syft/pkg/cataloger/redhat/parse_rpm_db.go b/syft/pkg/cataloger/redhat/parse_rpm_db.go index 785b2c9ad..7448432d3 100644 --- a/syft/pkg/cataloger/redhat/parse_rpm_db.go +++ b/syft/pkg/cataloger/redhat/parse_rpm_db.go @@ -89,6 +89,7 @@ func parseRpmDB(_ context.Context, resolver file.Resolver, env *generic.Environm metadata, distro, []string{entry.License}, + pkg.CompleteDependencies, ) if !pkg.IsValid(&p) { diff --git a/syft/pkg/cataloger/redhat/parse_rpm_db_test.go b/syft/pkg/cataloger/redhat/parse_rpm_db_test.go index 7572642c8..d7f80eef7 100644 --- a/syft/pkg/cataloger/redhat/parse_rpm_db_test.go +++ b/syft/pkg/cataloger/redhat/parse_rpm_db_test.go @@ -100,6 +100,7 @@ func TestParseRpmDB(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("MIT", packagesLocation), ), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.RpmDBEntry{ Name: "dive", Epoch: nil, @@ -130,6 +131,7 @@ func TestParseRpmDB(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("MIT", packagesLocation), ), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.RpmDBEntry{ Name: "dive", Epoch: nil, diff --git a/syft/pkg/cataloger/redhat/parse_rpm_manifest.go b/syft/pkg/cataloger/redhat/parse_rpm_manifest.go index 3e44ba8fd..dc7a9f868 100644 --- a/syft/pkg/cataloger/redhat/parse_rpm_manifest.go +++ b/syft/pkg/cataloger/redhat/parse_rpm_manifest.go @@ -44,7 +44,10 @@ func parseRpmManifest(_ context.Context, _ file.Resolver, _ *generic.Environment continue } - p := newDBPackage(reader.Location, *metadata, nil, nil) + // Create a new package representing the RPM manifest entry + // note: we don't know the quality of the manifest dependency information, so even though there are multiple + // packages, we can't discern the connectivity of completeness of the data. + p := newDBPackage(reader.Location, *metadata, nil, nil, pkg.IncompleteDependencies) if !pkg.IsValid(&p) { continue diff --git a/syft/pkg/cataloger/redhat/parse_rpm_manifest_test.go b/syft/pkg/cataloger/redhat/parse_rpm_manifest_test.go index 5a2cd2666..e7bce0c07 100644 --- a/syft/pkg/cataloger/redhat/parse_rpm_manifest_test.go +++ b/syft/pkg/cataloger/redhat/parse_rpm_manifest_test.go @@ -13,11 +13,12 @@ func TestParseRpmManifest(t *testing.T) { location := file.NewLocation(fixture) expected := []pkg.Package{ { - Name: "mariner-release", - Version: "2.0-12.cm2", - PURL: "pkg:rpm/mariner-release@2.0-12.cm2?arch=noarch&upstream=mariner-release-2.0-12.cm2.src.rpm", - Locations: file.NewLocationSet(location), - Type: pkg.RpmPkg, + Name: "mariner-release", + Version: "2.0-12.cm2", + PURL: "pkg:rpm/mariner-release@2.0-12.cm2?arch=noarch&upstream=mariner-release-2.0-12.cm2.src.rpm", + Locations: file.NewLocationSet(location), + Type: pkg.RpmPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.RpmDBEntry{ Name: "mariner-release", Epoch: nil, @@ -30,11 +31,12 @@ func TestParseRpmManifest(t *testing.T) { }, }, { - Name: "filesystem", - Version: "1.1-9.cm2", - PURL: "pkg:rpm/filesystem@1.1-9.cm2?arch=x86_64&upstream=filesystem-1.1-9.cm2.src.rpm", - Locations: file.NewLocationSet(location), - Type: pkg.RpmPkg, + Name: "filesystem", + Version: "1.1-9.cm2", + PURL: "pkg:rpm/filesystem@1.1-9.cm2?arch=x86_64&upstream=filesystem-1.1-9.cm2.src.rpm", + Locations: file.NewLocationSet(location), + Type: pkg.RpmPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.RpmDBEntry{ Name: "filesystem", Epoch: nil, @@ -47,11 +49,12 @@ func TestParseRpmManifest(t *testing.T) { }, }, { - Name: "glibc", - Version: "2.35-2.cm2", - PURL: "pkg:rpm/glibc@2.35-2.cm2?arch=x86_64&upstream=glibc-2.35-2.cm2.src.rpm", - Locations: file.NewLocationSet(location), - Type: pkg.RpmPkg, + Name: "glibc", + Version: "2.35-2.cm2", + PURL: "pkg:rpm/glibc@2.35-2.cm2?arch=x86_64&upstream=glibc-2.35-2.cm2.src.rpm", + Locations: file.NewLocationSet(location), + Type: pkg.RpmPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.RpmDBEntry{ Name: "glibc", Epoch: nil, @@ -64,11 +67,12 @@ func TestParseRpmManifest(t *testing.T) { }, }, { - Name: "openssl-libs", - Version: "1.1.1k-15.cm2", - PURL: "pkg:rpm/openssl-libs@1.1.1k-15.cm2?arch=x86_64&upstream=openssl-1.1.1k-15.cm2.src.rpm", - Locations: file.NewLocationSet(location), - Type: pkg.RpmPkg, + Name: "openssl-libs", + Version: "1.1.1k-15.cm2", + PURL: "pkg:rpm/openssl-libs@1.1.1k-15.cm2?arch=x86_64&upstream=openssl-1.1.1k-15.cm2.src.rpm", + Locations: file.NewLocationSet(location), + Type: pkg.RpmPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.RpmDBEntry{ Name: "openssl-libs", Epoch: nil, diff --git a/syft/pkg/cataloger/ruby/package.go b/syft/pkg/cataloger/ruby/package.go index 349fd5949..a00d2d7b4 100644 --- a/syft/pkg/cataloger/ruby/package.go +++ b/syft/pkg/cataloger/ruby/package.go @@ -14,6 +14,8 @@ func newGemfileLockPackage(name, version string, locations ...file.Location) pkg Locations: file.NewLocationSet(locations...), Language: pkg.Ruby, Type: pkg.GemPkg, + // no attempt is made by the parser function to resolve dependencies + Dependencies: pkg.IncompleteDependencies, } p.SetID() @@ -30,7 +32,9 @@ func newGemspecPackage(m gemData, gemSpecLocation file.Location) pkg.Package { PURL: packageURL(m.Name, m.Version), Language: pkg.Ruby, Type: pkg.GemPkg, - Metadata: m.RubyGemspec, + // no attempt is made by the parser function to resolve dependencies + Dependencies: pkg.IncompleteDependencies, + Metadata: m.RubyGemspec, } p.SetID() diff --git a/syft/pkg/cataloger/ruby/parse_gemfile_lock_test.go b/syft/pkg/cataloger/ruby/parse_gemfile_lock_test.go index ad94283aa..c5fb7c5c8 100644 --- a/syft/pkg/cataloger/ruby/parse_gemfile_lock_test.go +++ b/syft/pkg/cataloger/ruby/parse_gemfile_lock_test.go @@ -12,58 +12,58 @@ func TestParseGemfileLockEntries(t *testing.T) { fixture := "test-fixtures/Gemfile.lock" locations := file.NewLocationSet(file.NewLocation(fixture)) var expectedPkgs = []pkg.Package{ - {Name: "actionmailer", Version: "4.1.1", PURL: "pkg:gem/actionmailer@4.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "actionpack", Version: "4.1.1", PURL: "pkg:gem/actionpack@4.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "actionview", Version: "4.1.1", PURL: "pkg:gem/actionview@4.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "activemodel", Version: "4.1.1", PURL: "pkg:gem/activemodel@4.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "activerecord", Version: "4.1.1", PURL: "pkg:gem/activerecord@4.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "activesupport", Version: "4.1.1", PURL: "pkg:gem/activesupport@4.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "arel", Version: "5.0.1.20140414130214", PURL: "pkg:gem/arel@5.0.1.20140414130214", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "bootstrap-sass", Version: "3.1.1.1", PURL: "pkg:gem/bootstrap-sass@3.1.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "builder", Version: "3.2.2", PURL: "pkg:gem/builder@3.2.2", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "coffee-rails", Version: "4.0.1", PURL: "pkg:gem/coffee-rails@4.0.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "coffee-script", Version: "2.2.0", PURL: "pkg:gem/coffee-script@2.2.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "coffee-script-source", Version: "1.7.0", PURL: "pkg:gem/coffee-script-source@1.7.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "erubis", Version: "2.7.0", PURL: "pkg:gem/erubis@2.7.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "execjs", Version: "2.0.2", PURL: "pkg:gem/execjs@2.0.2", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "google-cloud-errors", Version: "1.3.0", PURL: "pkg:gem/google-cloud-errors@1.3.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "hike", Version: "1.2.3", PURL: "pkg:gem/hike@1.2.3", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "i18n", Version: "0.6.9", PURL: "pkg:gem/i18n@0.6.9", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "jbuilder", Version: "2.0.7", PURL: "pkg:gem/jbuilder@2.0.7", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "jquery-rails", Version: "3.1.0", PURL: "pkg:gem/jquery-rails@3.1.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "json", Version: "1.8.1", PURL: "pkg:gem/json@1.8.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "kgio", Version: "2.9.2", PURL: "pkg:gem/kgio@2.9.2", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "libv8", Version: "3.16.14.3", PURL: "pkg:gem/libv8@3.16.14.3", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "mail", Version: "2.5.4", PURL: "pkg:gem/mail@2.5.4", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "mime-types", Version: "1.25.1", PURL: "pkg:gem/mime-types@1.25.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "minitest", Version: "5.3.4", PURL: "pkg:gem/minitest@5.3.4", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "multi_json", Version: "1.10.1", PURL: "pkg:gem/multi_json@1.10.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "mysql2", Version: "0.3.16", PURL: "pkg:gem/mysql2@0.3.16", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "polyglot", Version: "0.3.4", PURL: "pkg:gem/polyglot@0.3.4", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "rack", Version: "1.5.2", PURL: "pkg:gem/rack@1.5.2", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "rack-test", Version: "0.6.2", PURL: "pkg:gem/rack-test@0.6.2", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "rails", Version: "4.1.1", PURL: "pkg:gem/rails@4.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "railties", Version: "4.1.1", PURL: "pkg:gem/railties@4.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "raindrops", Version: "0.13.0", PURL: "pkg:gem/raindrops@0.13.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "rake", Version: "10.3.2", PURL: "pkg:gem/rake@10.3.2", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "rdoc", Version: "4.1.1", PURL: "pkg:gem/rdoc@4.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "ref", Version: "1.0.5", PURL: "pkg:gem/ref@1.0.5", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "sass", Version: "3.2.19", PURL: "pkg:gem/sass@3.2.19", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "sass-rails", Version: "4.0.3", PURL: "pkg:gem/sass-rails@4.0.3", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "sdoc", Version: "0.4.0", PURL: "pkg:gem/sdoc@0.4.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "spring", Version: "1.1.3", PURL: "pkg:gem/spring@1.1.3", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "sprockets", Version: "2.11.0", PURL: "pkg:gem/sprockets@2.11.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "sprockets-rails", Version: "2.1.3", PURL: "pkg:gem/sprockets-rails@2.1.3", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "sqlite3", Version: "1.3.9", PURL: "pkg:gem/sqlite3@1.3.9", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "therubyracer", Version: "0.12.1", PURL: "pkg:gem/therubyracer@0.12.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "thor", Version: "0.19.1", PURL: "pkg:gem/thor@0.19.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "thread_safe", Version: "0.3.3", PURL: "pkg:gem/thread_safe@0.3.3", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "tilt", Version: "1.4.1", PURL: "pkg:gem/tilt@1.4.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "treetop", Version: "1.4.15", PURL: "pkg:gem/treetop@1.4.15", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "turbolinks", Version: "3.0.0", PURL: "pkg:gem/turbolinks@3.0.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "tzinfo", Version: "1.2.0", PURL: "pkg:gem/tzinfo@1.2.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "uglifier", Version: "2.5.0", PURL: "pkg:gem/uglifier@2.5.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "unicorn", Version: "4.8.3", PURL: "pkg:gem/unicorn@4.8.3", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, + {Name: "actionmailer", Version: "4.1.1", PURL: "pkg:gem/actionmailer@4.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "actionpack", Version: "4.1.1", PURL: "pkg:gem/actionpack@4.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "actionview", Version: "4.1.1", PURL: "pkg:gem/actionview@4.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "activemodel", Version: "4.1.1", PURL: "pkg:gem/activemodel@4.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "activerecord", Version: "4.1.1", PURL: "pkg:gem/activerecord@4.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "activesupport", Version: "4.1.1", PURL: "pkg:gem/activesupport@4.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "arel", Version: "5.0.1.20140414130214", PURL: "pkg:gem/arel@5.0.1.20140414130214", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "bootstrap-sass", Version: "3.1.1.1", PURL: "pkg:gem/bootstrap-sass@3.1.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "builder", Version: "3.2.2", PURL: "pkg:gem/builder@3.2.2", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "coffee-rails", Version: "4.0.1", PURL: "pkg:gem/coffee-rails@4.0.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "coffee-script", Version: "2.2.0", PURL: "pkg:gem/coffee-script@2.2.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "coffee-script-source", Version: "1.7.0", PURL: "pkg:gem/coffee-script-source@1.7.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "erubis", Version: "2.7.0", PURL: "pkg:gem/erubis@2.7.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "execjs", Version: "2.0.2", PURL: "pkg:gem/execjs@2.0.2", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "google-cloud-errors", Version: "1.3.0", PURL: "pkg:gem/google-cloud-errors@1.3.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "hike", Version: "1.2.3", PURL: "pkg:gem/hike@1.2.3", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "i18n", Version: "0.6.9", PURL: "pkg:gem/i18n@0.6.9", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "jbuilder", Version: "2.0.7", PURL: "pkg:gem/jbuilder@2.0.7", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "jquery-rails", Version: "3.1.0", PURL: "pkg:gem/jquery-rails@3.1.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "json", Version: "1.8.1", PURL: "pkg:gem/json@1.8.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "kgio", Version: "2.9.2", PURL: "pkg:gem/kgio@2.9.2", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "libv8", Version: "3.16.14.3", PURL: "pkg:gem/libv8@3.16.14.3", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "mail", Version: "2.5.4", PURL: "pkg:gem/mail@2.5.4", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "mime-types", Version: "1.25.1", PURL: "pkg:gem/mime-types@1.25.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "minitest", Version: "5.3.4", PURL: "pkg:gem/minitest@5.3.4", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "multi_json", Version: "1.10.1", PURL: "pkg:gem/multi_json@1.10.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "mysql2", Version: "0.3.16", PURL: "pkg:gem/mysql2@0.3.16", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "polyglot", Version: "0.3.4", PURL: "pkg:gem/polyglot@0.3.4", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "rack", Version: "1.5.2", PURL: "pkg:gem/rack@1.5.2", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "rack-test", Version: "0.6.2", PURL: "pkg:gem/rack-test@0.6.2", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "rails", Version: "4.1.1", PURL: "pkg:gem/rails@4.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "railties", Version: "4.1.1", PURL: "pkg:gem/railties@4.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "raindrops", Version: "0.13.0", PURL: "pkg:gem/raindrops@0.13.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "rake", Version: "10.3.2", PURL: "pkg:gem/rake@10.3.2", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "rdoc", Version: "4.1.1", PURL: "pkg:gem/rdoc@4.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "ref", Version: "1.0.5", PURL: "pkg:gem/ref@1.0.5", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "sass", Version: "3.2.19", PURL: "pkg:gem/sass@3.2.19", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "sass-rails", Version: "4.0.3", PURL: "pkg:gem/sass-rails@4.0.3", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "sdoc", Version: "0.4.0", PURL: "pkg:gem/sdoc@0.4.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "spring", Version: "1.1.3", PURL: "pkg:gem/spring@1.1.3", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "sprockets", Version: "2.11.0", PURL: "pkg:gem/sprockets@2.11.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "sprockets-rails", Version: "2.1.3", PURL: "pkg:gem/sprockets-rails@2.1.3", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "sqlite3", Version: "1.3.9", PURL: "pkg:gem/sqlite3@1.3.9", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "therubyracer", Version: "0.12.1", PURL: "pkg:gem/therubyracer@0.12.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "thor", Version: "0.19.1", PURL: "pkg:gem/thor@0.19.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "thread_safe", Version: "0.3.3", PURL: "pkg:gem/thread_safe@0.3.3", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "tilt", Version: "1.4.1", PURL: "pkg:gem/tilt@1.4.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "treetop", Version: "1.4.15", PURL: "pkg:gem/treetop@1.4.15", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "turbolinks", Version: "3.0.0", PURL: "pkg:gem/turbolinks@3.0.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "tzinfo", Version: "1.2.0", PURL: "pkg:gem/tzinfo@1.2.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "uglifier", Version: "2.5.0", PURL: "pkg:gem/uglifier@2.5.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, + {Name: "unicorn", Version: "4.8.3", PURL: "pkg:gem/unicorn@4.8.3", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.IncompleteDependencies}, } pkgtest.TestFileParser(t, fixture, parseGemFileLockEntries, expectedPkgs, nil) diff --git a/syft/pkg/cataloger/ruby/parse_gemspec_test.go b/syft/pkg/cataloger/ruby/parse_gemspec_test.go index f5ca64e95..2e063f1da 100644 --- a/syft/pkg/cataloger/ruby/parse_gemspec_test.go +++ b/syft/pkg/cataloger/ruby/parse_gemspec_test.go @@ -22,7 +22,8 @@ func TestParseGemspec(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("MIT", file.NewLocation(fixture)), ), - Language: pkg.Ruby, + Language: pkg.Ruby, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.RubyGemspec{ Name: "bundler", Version: "2.1.4", diff --git a/syft/pkg/cataloger/rust/cataloger_test.go b/syft/pkg/cataloger/rust/cataloger_test.go index 3a7a356db..550f18943 100644 --- a/syft/pkg/cataloger/rust/cataloger_test.go +++ b/syft/pkg/cataloger/rust/cataloger_test.go @@ -12,13 +12,14 @@ func TestNewAuditBinaryCataloger(t *testing.T) { expectedPkgs := []pkg.Package{ { - Name: "auditable", - Version: "0.1.0", - PURL: "pkg:cargo/auditable@0.1.0", - FoundBy: "cargo-auditable-binary-cataloger", - Locations: file.NewLocationSet(file.NewVirtualLocation("/hello-auditable", "/hello-auditable")), - Language: pkg.Rust, - Type: pkg.RustPkg, + Name: "auditable", + Version: "0.1.0", + PURL: "pkg:cargo/auditable@0.1.0", + FoundBy: "cargo-auditable-binary-cataloger", + Locations: file.NewLocationSet(file.NewVirtualLocation("/hello-auditable", "/hello-auditable")), + Language: pkg.Rust, + Type: pkg.RustPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.RustBinaryAuditEntry{ Name: "auditable", Version: "0.1.0", @@ -26,13 +27,14 @@ func TestNewAuditBinaryCataloger(t *testing.T) { }, }, { - Name: "hello-auditable", - Version: "0.1.0", - PURL: "pkg:cargo/hello-auditable@0.1.0", - FoundBy: "cargo-auditable-binary-cataloger", - Locations: file.NewLocationSet(file.NewVirtualLocation("/hello-auditable", "/hello-auditable")), - Language: pkg.Rust, - Type: pkg.RustPkg, + Name: "hello-auditable", + Version: "0.1.0", + PURL: "pkg:cargo/hello-auditable@0.1.0", + FoundBy: "cargo-auditable-binary-cataloger", + Locations: file.NewLocationSet(file.NewVirtualLocation("/hello-auditable", "/hello-auditable")), + Language: pkg.Rust, + Type: pkg.RustPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.RustBinaryAuditEntry{ Name: "hello-auditable", Version: "0.1.0", diff --git a/syft/pkg/cataloger/rust/package.go b/syft/pkg/cataloger/rust/package.go index be67d96a9..3444a0edd 100644 --- a/syft/pkg/cataloger/rust/package.go +++ b/syft/pkg/cataloger/rust/package.go @@ -11,13 +11,14 @@ import ( // Pkg returns the standard `pkg.Package` representation of the package referenced within the Cargo.lock metadata. func newPackageFromCargoMetadata(m pkg.RustCargoLockEntry, locations ...file.Location) pkg.Package { p := pkg.Package{ - Name: m.Name, - Version: m.Version, - Locations: file.NewLocationSet(locations...), - PURL: packageURL(m.Name, m.Version), - Language: pkg.Rust, - Type: pkg.RustPkg, - Metadata: m, + Name: m.Name, + Version: m.Version, + Locations: file.NewLocationSet(locations...), + PURL: packageURL(m.Name, m.Version), + Language: pkg.Rust, + Type: pkg.RustPkg, + Dependencies: pkg.CompleteDependencies, + Metadata: m, } p.SetID() @@ -46,6 +47,8 @@ func newPackageFromAudit(dep *rustaudit.Package, locations ...file.Location) pkg Language: pkg.Rust, Type: pkg.RustPkg, Locations: file.NewLocationSet(locations...), + // no attempt is made by the parser function to resolve dependencies + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.RustBinaryAuditEntry{ Name: dep.Name, Version: dep.Version, diff --git a/syft/pkg/cataloger/rust/parse_cargo_lock_test.go b/syft/pkg/cataloger/rust/parse_cargo_lock_test.go index 2d7d2b4b6..8c65e09d0 100644 --- a/syft/pkg/cataloger/rust/parse_cargo_lock_test.go +++ b/syft/pkg/cataloger/rust/parse_cargo_lock_test.go @@ -13,13 +13,14 @@ func TestParseCargoLock(t *testing.T) { fixture := "test-fixtures/Cargo.lock" locations := file.NewLocationSet(file.NewLocation(fixture)) ansiTerm := pkg.Package{ - Name: "ansi_term", - Version: "0.12.1", - PURL: "pkg:cargo/ansi_term@0.12.1", - Locations: locations, - Language: pkg.Rust, - Type: pkg.RustPkg, - Licenses: pkg.NewLicenseSet(), + Name: "ansi_term", + Version: "0.12.1", + PURL: "pkg:cargo/ansi_term@0.12.1", + Locations: locations, + Language: pkg.Rust, + Type: pkg.RustPkg, + Licenses: pkg.NewLicenseSet(), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.RustCargoLockEntry{ Name: "ansi_term", Version: "0.12.1", @@ -31,13 +32,14 @@ func TestParseCargoLock(t *testing.T) { }, } errno := pkg.Package{ - Name: "errno", - Version: "0.3.9", - PURL: "pkg:cargo/errno@0.3.9", - Locations: locations, - Language: pkg.Rust, - Type: pkg.RustPkg, - Licenses: pkg.NewLicenseSet(), + Name: "errno", + Version: "0.3.9", + PURL: "pkg:cargo/errno@0.3.9", + Locations: locations, + Language: pkg.Rust, + Type: pkg.RustPkg, + Licenses: pkg.NewLicenseSet(), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.RustCargoLockEntry{ Name: "errno", Version: "0.3.9", @@ -49,13 +51,14 @@ func TestParseCargoLock(t *testing.T) { }, } matches := pkg.Package{ - Name: "matches", - Version: "0.1.8", - PURL: "pkg:cargo/matches@0.1.8", - Locations: locations, - Language: pkg.Rust, - Type: pkg.RustPkg, - Licenses: pkg.NewLicenseSet(), + Name: "matches", + Version: "0.1.8", + PURL: "pkg:cargo/matches@0.1.8", + Locations: locations, + Language: pkg.Rust, + Type: pkg.RustPkg, + Licenses: pkg.NewLicenseSet(), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.RustCargoLockEntry{ Name: "matches", Version: "0.1.8", @@ -65,13 +68,14 @@ func TestParseCargoLock(t *testing.T) { }, } memchr := pkg.Package{ - Name: "memchr", - Version: "2.3.3", - PURL: "pkg:cargo/memchr@2.3.3", - Locations: locations, - Language: pkg.Rust, - Type: pkg.RustPkg, - Licenses: pkg.NewLicenseSet(), + Name: "memchr", + Version: "2.3.3", + PURL: "pkg:cargo/memchr@2.3.3", + Locations: locations, + Language: pkg.Rust, + Type: pkg.RustPkg, + Licenses: pkg.NewLicenseSet(), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.RustCargoLockEntry{ Name: "memchr", Version: "2.3.3", @@ -82,13 +86,14 @@ func TestParseCargoLock(t *testing.T) { } natord := pkg.Package{ - Name: "natord", - Version: "1.0.9", - PURL: "pkg:cargo/natord@1.0.9", - Locations: locations, - Language: pkg.Rust, - Type: pkg.RustPkg, - Licenses: pkg.NewLicenseSet(), + Name: "natord", + Version: "1.0.9", + PURL: "pkg:cargo/natord@1.0.9", + Locations: locations, + Language: pkg.Rust, + Type: pkg.RustPkg, + Licenses: pkg.NewLicenseSet(), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.RustCargoLockEntry{ Name: "natord", Version: "1.0.9", @@ -99,13 +104,14 @@ func TestParseCargoLock(t *testing.T) { } nom := pkg.Package{ - Name: "nom", - Version: "4.2.3", - PURL: "pkg:cargo/nom@4.2.3", - Locations: locations, - Language: pkg.Rust, - Type: pkg.RustPkg, - Licenses: pkg.NewLicenseSet(), + Name: "nom", + Version: "4.2.3", + PURL: "pkg:cargo/nom@4.2.3", + Locations: locations, + Language: pkg.Rust, + Type: pkg.RustPkg, + Licenses: pkg.NewLicenseSet(), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.RustCargoLockEntry{ Name: "nom", Version: "4.2.3", @@ -118,13 +124,14 @@ func TestParseCargoLock(t *testing.T) { }, } schannel := pkg.Package{ - Name: "schannel", - Version: "0.1.26", - PURL: "pkg:cargo/schannel@0.1.26", - Locations: locations, - Language: pkg.Rust, - Type: pkg.RustPkg, - Licenses: pkg.NewLicenseSet(), + Name: "schannel", + Version: "0.1.26", + PURL: "pkg:cargo/schannel@0.1.26", + Locations: locations, + Language: pkg.Rust, + Type: pkg.RustPkg, + Licenses: pkg.NewLicenseSet(), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.RustCargoLockEntry{ Name: "schannel", Version: "0.1.26", @@ -137,13 +144,14 @@ func TestParseCargoLock(t *testing.T) { } unicodeBidi := pkg.Package{ - Name: "unicode-bidi", - Version: "0.3.4", - PURL: "pkg:cargo/unicode-bidi@0.3.4", - Locations: locations, - Language: pkg.Rust, - Type: pkg.RustPkg, - Licenses: pkg.NewLicenseSet(), + Name: "unicode-bidi", + Version: "0.3.4", + PURL: "pkg:cargo/unicode-bidi@0.3.4", + Locations: locations, + Language: pkg.Rust, + Type: pkg.RustPkg, + Licenses: pkg.NewLicenseSet(), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.RustCargoLockEntry{ Name: "unicode-bidi", Version: "0.3.4", @@ -157,13 +165,14 @@ func TestParseCargoLock(t *testing.T) { } versionCheck := pkg.Package{ - Name: "version_check", - Version: "0.1.5", - PURL: "pkg:cargo/version_check@0.1.5", - Locations: locations, - Language: pkg.Rust, - Type: pkg.RustPkg, - Licenses: pkg.NewLicenseSet(), + Name: "version_check", + Version: "0.1.5", + PURL: "pkg:cargo/version_check@0.1.5", + Locations: locations, + Language: pkg.Rust, + Type: pkg.RustPkg, + Licenses: pkg.NewLicenseSet(), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.RustCargoLockEntry{ Name: "version_check", Version: "0.1.5", @@ -174,13 +183,14 @@ func TestParseCargoLock(t *testing.T) { } winapi := pkg.Package{ - Name: "winapi", - Version: "0.3.9", - PURL: "pkg:cargo/winapi@0.3.9", - Locations: locations, - Language: pkg.Rust, - Type: pkg.RustPkg, - Licenses: pkg.NewLicenseSet(), + Name: "winapi", + Version: "0.3.9", + PURL: "pkg:cargo/winapi@0.3.9", + Locations: locations, + Language: pkg.Rust, + Type: pkg.RustPkg, + Licenses: pkg.NewLicenseSet(), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.RustCargoLockEntry{ Name: "winapi", Version: "0.3.9", @@ -194,13 +204,14 @@ func TestParseCargoLock(t *testing.T) { } winAPIi686PCWindowsGNU := pkg.Package{ - Name: "winapi-i686-pc-windows-gnu", - Version: "0.4.0", - PURL: "pkg:cargo/winapi-i686-pc-windows-gnu@0.4.0", - Locations: locations, - Language: pkg.Rust, - Type: pkg.RustPkg, - Licenses: pkg.NewLicenseSet(), + Name: "winapi-i686-pc-windows-gnu", + Version: "0.4.0", + PURL: "pkg:cargo/winapi-i686-pc-windows-gnu@0.4.0", + Locations: locations, + Language: pkg.Rust, + Type: pkg.RustPkg, + Licenses: pkg.NewLicenseSet(), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.RustCargoLockEntry{ Name: "winapi-i686-pc-windows-gnu", Version: "0.4.0", @@ -211,13 +222,14 @@ func TestParseCargoLock(t *testing.T) { } winAPIx8664PCWindowsGNU := pkg.Package{ - Name: "winapi-x86_64-pc-windows-gnu", - Version: "0.4.0", - PURL: "pkg:cargo/winapi-x86_64-pc-windows-gnu@0.4.0", - Locations: locations, - Language: pkg.Rust, - Type: pkg.RustPkg, - Licenses: pkg.NewLicenseSet(), + Name: "winapi-x86_64-pc-windows-gnu", + Version: "0.4.0", + PURL: "pkg:cargo/winapi-x86_64-pc-windows-gnu@0.4.0", + Locations: locations, + Language: pkg.Rust, + Type: pkg.RustPkg, + Licenses: pkg.NewLicenseSet(), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.RustCargoLockEntry{ Name: "winapi-x86_64-pc-windows-gnu", Version: "0.4.0", @@ -228,13 +240,14 @@ func TestParseCargoLock(t *testing.T) { } windowsSys52 := pkg.Package{ - Name: "windows-sys", - Version: "0.52.0", - PURL: "pkg:cargo/windows-sys@0.52.0", - Locations: locations, - Language: pkg.Rust, - Type: pkg.RustPkg, - Licenses: pkg.NewLicenseSet(), + Name: "windows-sys", + Version: "0.52.0", + PURL: "pkg:cargo/windows-sys@0.52.0", + Locations: locations, + Language: pkg.Rust, + Type: pkg.RustPkg, + Licenses: pkg.NewLicenseSet(), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.RustCargoLockEntry{ Name: "windows-sys", Version: "0.52.0", @@ -245,13 +258,14 @@ func TestParseCargoLock(t *testing.T) { } windowsSys59 := pkg.Package{ - Name: "windows-sys", - Version: "0.59.0", - PURL: "pkg:cargo/windows-sys@0.59.0", - Locations: locations, - Language: pkg.Rust, - Type: pkg.RustPkg, - Licenses: pkg.NewLicenseSet(), + Name: "windows-sys", + Version: "0.59.0", + PURL: "pkg:cargo/windows-sys@0.59.0", + Locations: locations, + Language: pkg.Rust, + Type: pkg.RustPkg, + Licenses: pkg.NewLicenseSet(), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.RustCargoLockEntry{ Name: "windows-sys", Version: "0.59.0", diff --git a/syft/pkg/cataloger/sbom/cataloger.go b/syft/pkg/cataloger/sbom/cataloger.go index 9779a8166..e1483d459 100644 --- a/syft/pkg/cataloger/sbom/cataloger.go +++ b/syft/pkg/cataloger/sbom/cataloger.go @@ -54,15 +54,21 @@ func parseSBOM(_ context.Context, _ file.Resolver, _ *generic.Environment, reade var pkgs []pkg.Package relationships := s.Relationships + + for i := range relationships { + if p, ok := relationships[i].To.(pkg.Package); ok { + finalizePkg(&p, reader.Location) + relationships[i].To = p + } + + if p, ok := relationships[i].From.(pkg.Package); ok { + finalizePkg(&p, reader.Location) + relationships[i].From = p + } + } + for _, p := range s.Artifacts.Packages.Sorted() { - // replace all locations on the package with the location of the SBOM file. - // Why not keep the original list of locations? Since the "locations" field is meant to capture - // where there is evidence of this file, and the catalogers have not run against any file other than, - // the SBOM, this is the only location that is relevant for this cataloger. - p.Locations = file.NewLocationSet( - reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), - ) - p.FoundBy = catalogerName + finalizePkg(&p, reader.Location) pkgs = append(pkgs, p) relationships = append(relationships, artifact.Relationship{ @@ -75,6 +81,22 @@ func parseSBOM(_ context.Context, _ file.Resolver, _ *generic.Environment, reade return pkgs, relationships, nil } +func finalizePkg(p *pkg.Package, loc file.Location) { + // replace all locations on the package with the location of the SBOM file. + // Why not keep the original list of locations? Since the "locations" field is meant to capture + // where there is evidence of this file, and the catalogers have not run against any file other than, + // the SBOM, this is the only location that is relevant for this cataloger. + p.Locations = file.NewLocationSet( + loc.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + ) + p.FoundBy = catalogerName + + // we are entirely unaware of the quality of the SBOM being read from, the ecosystem really in use, the context + // where it was found, and thus are not able to reason about the dependency resolution mechanisms that + // are in play. + p.Dependencies = pkg.UnknownDependencyCompleteness +} + func adaptToReadSeeker(reader io.Reader) (io.ReadSeeker, error) { // with the stereoscope API and default file.Resolver implementation here in syft, odds are very high that // the underlying reader is already a ReadSeeker, so we can just return it as-is. We still want to diff --git a/syft/pkg/cataloger/sbom/cataloger_test.go b/syft/pkg/cataloger/sbom/cataloger_test.go index e53b14ae7..a833d9357 100644 --- a/syft/pkg/cataloger/sbom/cataloger_test.go +++ b/syft/pkg/cataloger/sbom/cataloger_test.go @@ -20,15 +20,18 @@ func mustCPEs(s ...string) (c []cpe.CPE) { } func Test_parseSBOM(t *testing.T) { + sbomLocations := file.NewLocationSet(file.NewLocation("sbom.syft.json")) + expectedPkgs := []pkg.Package{ { - Name: "alpine-baselayout", - Version: "3.2.0-r23", - Type: "apk", - Locations: file.NewLocationSet(file.NewLocation("sbom.syft.json")), - Licenses: pkg.NewLicenseSet(pkg.NewLicense("GPL-2.0-only")), - FoundBy: "sbom-cataloger", - PURL: "pkg:apk/alpine/alpine-baselayout@3.2.0-r23?arch=x86_64&upstream=alpine-baselayout&distro=alpine-3.16.3", + Name: "alpine-baselayout", + Version: "3.2.0-r23", + Type: "apk", + Locations: sbomLocations, + Licenses: pkg.NewLicenseSet(pkg.NewLicense("GPL-2.0-only")), + FoundBy: "sbom-cataloger", + PURL: "pkg:apk/alpine/alpine-baselayout@3.2.0-r23?arch=x86_64&upstream=alpine-baselayout&distro=alpine-3.16.3", + Dependencies: pkg.UnknownDependencyCompleteness, CPEs: mustCPEs( "cpe:2.3:a:alpine-baselayout:alpine-baselayout:3.2.0-r23:*:*:*:*:*:*:*", "cpe:2.3:a:alpine-baselayout:alpine_baselayout:3.2.0-r23:*:*:*:*:*:*:*", @@ -39,13 +42,14 @@ func Test_parseSBOM(t *testing.T) { ), }, { - Name: "alpine-baselayout-data", - Version: "3.2.0-r23", - Type: "apk", - Locations: file.NewLocationSet(file.NewLocation("sbom.syft.json")), - Licenses: pkg.NewLicenseSet(pkg.NewLicense("GPL-2.0-only")), - FoundBy: "sbom-cataloger", - PURL: "pkg:apk/alpine/alpine-baselayout-data@3.2.0-r23?arch=x86_64&upstream=alpine-baselayout&distro=alpine-3.16.3", + Name: "alpine-baselayout-data", + Version: "3.2.0-r23", + Type: "apk", + Locations: sbomLocations, + Licenses: pkg.NewLicenseSet(pkg.NewLicense("GPL-2.0-only")), + FoundBy: "sbom-cataloger", + PURL: "pkg:apk/alpine/alpine-baselayout-data@3.2.0-r23?arch=x86_64&upstream=alpine-baselayout&distro=alpine-3.16.3", + Dependencies: pkg.UnknownDependencyCompleteness, CPEs: mustCPEs( "cpe:2.3:a:alpine-baselayout-data:alpine-baselayout-data:3.2.0-r23:*:*:*:*:*:*:*", "cpe:2.3:a:alpine-baselayout-data:alpine_baselayout_data:3.2.0-r23:*:*:*:*:*:*:*", @@ -60,13 +64,14 @@ func Test_parseSBOM(t *testing.T) { ), }, { - Name: "alpine-keys", - Version: "2.4-r1", - Type: "apk", - Locations: file.NewLocationSet(file.NewLocation("sbom.syft.json")), - Licenses: pkg.NewLicenseSet(pkg.NewLicense("MIT")), - FoundBy: "sbom-cataloger", - PURL: "pkg:apk/alpine/alpine-keys@2.4-r1?arch=x86_64&upstream=alpine-keys&distro=alpine-3.16.3", + Name: "alpine-keys", + Version: "2.4-r1", + Type: "apk", + Locations: sbomLocations, + Licenses: pkg.NewLicenseSet(pkg.NewLicense("MIT")), + FoundBy: "sbom-cataloger", + PURL: "pkg:apk/alpine/alpine-keys@2.4-r1?arch=x86_64&upstream=alpine-keys&distro=alpine-3.16.3", + Dependencies: pkg.UnknownDependencyCompleteness, CPEs: mustCPEs( "cpe:2.3:a:alpine-keys:alpine-keys:2.4-r1:*:*:*:*:*:*:*", "cpe:2.3:a:alpine-keys:alpine_keys:2.4-r1:*:*:*:*:*:*:*", @@ -77,13 +82,14 @@ func Test_parseSBOM(t *testing.T) { ), }, { - Name: "apk-tools", - Version: "2.12.9-r3", - Type: "apk", - Locations: file.NewLocationSet(file.NewLocation("sbom.syft.json")), - Licenses: pkg.NewLicenseSet(pkg.NewLicense("GPL-2.0-only")), - FoundBy: "sbom-cataloger", - PURL: "pkg:apk/alpine/apk-tools@2.12.9-r3?arch=x86_64&upstream=apk-tools&distro=alpine-3.16.3", + Name: "apk-tools", + Version: "2.12.9-r3", + Type: "apk", + Locations: sbomLocations, + Licenses: pkg.NewLicenseSet(pkg.NewLicense("GPL-2.0-only")), + FoundBy: "sbom-cataloger", + PURL: "pkg:apk/alpine/apk-tools@2.12.9-r3?arch=x86_64&upstream=apk-tools&distro=alpine-3.16.3", + Dependencies: pkg.UnknownDependencyCompleteness, CPEs: mustCPEs( "cpe:2.3:a:apk-tools:apk-tools:2.12.9-r3:*:*:*:*:*:*:*", "cpe:2.3:a:apk-tools:apk_tools:2.12.9-r3:*:*:*:*:*:*:*", @@ -94,13 +100,14 @@ func Test_parseSBOM(t *testing.T) { ), }, { - Name: "busybox", - Version: "1.35.0-r17", - Type: "apk", - Locations: file.NewLocationSet(file.NewLocation("sbom.syft.json")), - Licenses: pkg.NewLicenseSet(pkg.NewLicense("GPL-2.0-only")), - FoundBy: "sbom-cataloger", - PURL: "pkg:apk/alpine/busybox@1.35.0-r17?arch=x86_64&upstream=busybox&distro=alpine-3.16.3", + Name: "busybox", + Version: "1.35.0-r17", + Type: "apk", + Locations: sbomLocations, + Licenses: pkg.NewLicenseSet(pkg.NewLicense("GPL-2.0-only")), + FoundBy: "sbom-cataloger", + PURL: "pkg:apk/alpine/busybox@1.35.0-r17?arch=x86_64&upstream=busybox&distro=alpine-3.16.3", + Dependencies: pkg.UnknownDependencyCompleteness, CPEs: mustCPEs( "cpe:2.3:a:busybox:busybox:1.35.0-r17:*:*:*:*:*:*:*", ), @@ -109,13 +116,14 @@ func Test_parseSBOM(t *testing.T) { Name: "ca-certificates-bundle", Version: "20220614-r0", Type: "apk", - Locations: file.NewLocationSet(file.NewLocation("sbom.syft.json")), + Locations: sbomLocations, Licenses: pkg.NewLicenseSet( pkg.NewLicense("MPL-2.0"), pkg.NewLicense("MIT"), ), - FoundBy: "sbom-cataloger", - PURL: "pkg:apk/alpine/ca-certificates-bundle@20220614-r0?arch=x86_64&upstream=ca-certificates&distro=alpine-3.16.3", + FoundBy: "sbom-cataloger", + PURL: "pkg:apk/alpine/ca-certificates-bundle@20220614-r0?arch=x86_64&upstream=ca-certificates&distro=alpine-3.16.3", + Dependencies: pkg.UnknownDependencyCompleteness, CPEs: mustCPEs( "cpe:2.3:a:ca-certificates-bundle:ca-certificates-bundle:20220614-r0:*:*:*:*:*:*:*", "cpe:2.3:a:ca-certificates-bundle:ca_certificates_bundle:20220614-r0:*:*:*:*:*:*:*", @@ -133,13 +141,14 @@ func Test_parseSBOM(t *testing.T) { Name: "libc-utils", Version: "0.7.2-r3", Type: "apk", - Locations: file.NewLocationSet(file.NewLocation("sbom.syft.json")), + Locations: sbomLocations, Licenses: pkg.NewLicenseSet( pkg.NewLicense("BSD-2-Clause"), pkg.NewLicense("BSD-3-Clause"), ), - FoundBy: "sbom-cataloger", - PURL: "pkg:apk/alpine/libc-utils@0.7.2-r3?arch=x86_64&upstream=libc-dev&distro=alpine-3.16.3", + FoundBy: "sbom-cataloger", + PURL: "pkg:apk/alpine/libc-utils@0.7.2-r3?arch=x86_64&upstream=libc-dev&distro=alpine-3.16.3", + Dependencies: pkg.UnknownDependencyCompleteness, CPEs: mustCPEs( "cpe:2.3:a:libc-utils:libc-utils:0.7.2-r3:*:*:*:*:*:*:*", "cpe:2.3:a:libc-utils:libc_utils:0.7.2-r3:*:*:*:*:*:*:*", @@ -150,37 +159,40 @@ func Test_parseSBOM(t *testing.T) { ), }, { - Name: "libcrypto1.1", - Version: "1.1.1s-r0", - Type: "apk", - Locations: file.NewLocationSet(file.NewLocation("sbom.syft.json")), - Licenses: pkg.NewLicenseSet(pkg.NewLicense("OpenSSL")), // SPDX expression is not set - FoundBy: "sbom-cataloger", - PURL: "pkg:apk/alpine/libcrypto1.1@1.1.1s-r0?arch=x86_64&upstream=openssl&distro=alpine-3.16.3", + Name: "libcrypto1.1", + Version: "1.1.1s-r0", + Type: "apk", + Locations: sbomLocations, + Licenses: pkg.NewLicenseSet(pkg.NewLicense("OpenSSL")), // SPDX expression is not set + FoundBy: "sbom-cataloger", + PURL: "pkg:apk/alpine/libcrypto1.1@1.1.1s-r0?arch=x86_64&upstream=openssl&distro=alpine-3.16.3", + Dependencies: pkg.UnknownDependencyCompleteness, CPEs: mustCPEs( "cpe:2.3:a:libcrypto1.1:libcrypto1.1:1.1.1s-r0:*:*:*:*:*:*:*", ), }, { - Name: "libssl1.1", - Version: "1.1.1s-r0", - Type: "apk", - Locations: file.NewLocationSet(file.NewLocation("sbom.syft.json")), - Licenses: pkg.NewLicenseSet(pkg.NewLicense("OpenSSL")), // SPDX expression is not set - FoundBy: "sbom-cataloger", - PURL: "pkg:apk/alpine/libssl1.1@1.1.1s-r0?arch=x86_64&upstream=openssl&distro=alpine-3.16.3", + Name: "libssl1.1", + Version: "1.1.1s-r0", + Type: "apk", + Locations: sbomLocations, + Licenses: pkg.NewLicenseSet(pkg.NewLicense("OpenSSL")), // SPDX expression is not set + FoundBy: "sbom-cataloger", + PURL: "pkg:apk/alpine/libssl1.1@1.1.1s-r0?arch=x86_64&upstream=openssl&distro=alpine-3.16.3", + Dependencies: pkg.UnknownDependencyCompleteness, CPEs: mustCPEs( "cpe:2.3:a:libssl1.1:libssl1.1:1.1.1s-r0:*:*:*:*:*:*:*", ), }, { - Name: "musl", - Version: "1.2.3-r1", - Type: "apk", - Locations: file.NewLocationSet(file.NewLocation("sbom.syft.json")), - Licenses: pkg.NewLicenseSet(pkg.NewLicense("MIT")), // SPDX expression is not set - FoundBy: "sbom-cataloger", - PURL: "pkg:apk/alpine/musl@1.2.3-r1?arch=x86_64&upstream=musl&distro=alpine-3.16.3", + Name: "musl", + Version: "1.2.3-r1", + Type: "apk", + Locations: sbomLocations, + Licenses: pkg.NewLicenseSet(pkg.NewLicense("MIT")), // SPDX expression is not set + FoundBy: "sbom-cataloger", + PURL: "pkg:apk/alpine/musl@1.2.3-r1?arch=x86_64&upstream=musl&distro=alpine-3.16.3", + Dependencies: pkg.UnknownDependencyCompleteness, CPEs: mustCPEs( "cpe:2.3:a:musl:musl:1.2.3-r1:*:*:*:*:*:*:*", ), @@ -189,14 +201,15 @@ func Test_parseSBOM(t *testing.T) { Name: "musl-utils", Version: "1.2.3-r1", Type: "apk", - Locations: file.NewLocationSet(file.NewLocation("sbom.syft.json")), + Locations: sbomLocations, Licenses: pkg.NewLicenseSet( pkg.NewLicense("MIT"), pkg.NewLicense("BSD"), pkg.NewLicense("GPL2+"), // SPDX expression is not set ), - FoundBy: "sbom-cataloger", - PURL: "pkg:apk/alpine/musl-utils@1.2.3-r1?arch=x86_64&upstream=musl&distro=alpine-3.16.3", + FoundBy: "sbom-cataloger", + PURL: "pkg:apk/alpine/musl-utils@1.2.3-r1?arch=x86_64&upstream=musl&distro=alpine-3.16.3", + Dependencies: pkg.UnknownDependencyCompleteness, CPEs: mustCPEs( "cpe:2.3:a:musl-utils:musl-utils:1.2.3-r1:*:*:*:*:*:*:*", "cpe:2.3:a:musl-utils:musl_utils:1.2.3-r1:*:*:*:*:*:*:*", @@ -210,12 +223,13 @@ func Test_parseSBOM(t *testing.T) { Name: "scanelf", Version: "1.3.4-r0", Type: "apk", - Locations: file.NewLocationSet(file.NewLocation("sbom.syft.json")), + Locations: sbomLocations, Licenses: pkg.NewLicenseSet( pkg.NewLicense("GPL-2.0-only"), ), - FoundBy: "sbom-cataloger", - PURL: "pkg:apk/alpine/scanelf@1.3.4-r0?arch=x86_64&upstream=pax-utils&distro=alpine-3.16.3", + FoundBy: "sbom-cataloger", + PURL: "pkg:apk/alpine/scanelf@1.3.4-r0?arch=x86_64&upstream=pax-utils&distro=alpine-3.16.3", + Dependencies: pkg.UnknownDependencyCompleteness, CPEs: mustCPEs( "cpe:2.3:a:scanelf:scanelf:1.3.4-r0:*:*:*:*:*:*:*", ), @@ -224,12 +238,13 @@ func Test_parseSBOM(t *testing.T) { Name: "ssl_client", Version: "1.35.0-r17", Type: "apk", - Locations: file.NewLocationSet(file.NewLocation("sbom.syft.json")), + Locations: sbomLocations, Licenses: pkg.NewLicenseSet( pkg.NewLicense("GPL-2.0-only"), ), - FoundBy: "sbom-cataloger", - PURL: "pkg:apk/alpine/ssl_client@1.35.0-r17?arch=x86_64&upstream=busybox&distro=alpine-3.16.3", + FoundBy: "sbom-cataloger", + PURL: "pkg:apk/alpine/ssl_client@1.35.0-r17?arch=x86_64&upstream=busybox&distro=alpine-3.16.3", + Dependencies: pkg.UnknownDependencyCompleteness, CPEs: mustCPEs( "cpe:2.3:a:ssl-client:ssl-client:1.35.0-r17:*:*:*:*:*:*:*", "cpe:2.3:a:ssl-client:ssl_client:1.35.0-r17:*:*:*:*:*:*:*", @@ -243,48 +258,42 @@ func Test_parseSBOM(t *testing.T) { Name: "zlib", Version: "1.2.12-r3", Type: "apk", - Locations: file.NewLocationSet(file.NewLocation("sbom.syft.json")), + Locations: sbomLocations, Licenses: pkg.NewLicenseSet( pkg.NewLicense("Zlib"), ), - FoundBy: "sbom-cataloger", - PURL: "pkg:apk/alpine/zlib@1.2.12-r3?arch=x86_64&upstream=zlib&distro=alpine-3.16.3", + FoundBy: "sbom-cataloger", + PURL: "pkg:apk/alpine/zlib@1.2.12-r3?arch=x86_64&upstream=zlib&distro=alpine-3.16.3", + Dependencies: pkg.UnknownDependencyCompleteness, CPEs: mustCPEs( "cpe:2.3:a:zlib:zlib:1.2.12-r3:*:*:*:*:*:*:*", ), }, } - apkgdbLocation := file.NewLocationSet(file.Location{ - LocationData: file.LocationData{ - Coordinates: file.Coordinates{ - RealPath: "/lib/apk/db/installed", - FileSystemID: "sha256:e5e13b0c77cbb769548077189c3da2f0a764ceca06af49d8d558e759f5c232bd", - }, - }, - }) - libSSL := pkg.Package{ - Name: "libssl1.1", - Version: "1.1.1s-r0", - Type: "apk", - Locations: apkgdbLocation, - Licenses: pkg.NewLicenseSet(pkg.NewLicense("OpenSSL")), - FoundBy: "apkdb-cataloger", - PURL: "pkg:apk/alpine/libssl1.1@1.1.1s-r0?arch=x86_64&upstream=openssl&distro=alpine-3.16.3", + Name: "libssl1.1", + Version: "1.1.1s-r0", + Type: "apk", + Locations: sbomLocations, + Licenses: pkg.NewLicenseSet(pkg.NewLicense("OpenSSL")), + FoundBy: "sbom-cataloger", + PURL: "pkg:apk/alpine/libssl1.1@1.1.1s-r0?arch=x86_64&upstream=openssl&distro=alpine-3.16.3", + Dependencies: pkg.UnknownDependencyCompleteness, CPEs: mustCPEs( "cpe:2.3:a:libssl1.1:libssl1.1:1.1.1s-r0:*:*:*:*:*:*:*", ), } sslClient := pkg.Package{ - Name: "ssl_client", - Version: "1.35.0-r17", - Type: "apk", - Locations: apkgdbLocation, - Licenses: pkg.NewLicenseSet(pkg.NewLicense("GPL-2.0-only")), - FoundBy: "apkdb-cataloger", - PURL: "pkg:apk/alpine/ssl_client@1.35.0-r17?arch=x86_64&upstream=busybox&distro=alpine-3.16.3", + Name: "ssl_client", + Version: "1.35.0-r17", + Type: "apk", + Locations: sbomLocations, + Licenses: pkg.NewLicenseSet(pkg.NewLicense("GPL-2.0-only")), + FoundBy: "sbom-cataloger", + PURL: "pkg:apk/alpine/ssl_client@1.35.0-r17?arch=x86_64&upstream=busybox&distro=alpine-3.16.3", + Dependencies: pkg.UnknownDependencyCompleteness, CPEs: mustCPEs( "cpe:2.3:a:ssl-client:ssl-client:1.35.0-r17:*:*:*:*:*:*:*", "cpe:2.3:a:ssl-client:ssl_client:1.35.0-r17:*:*:*:*:*:*:*", @@ -296,13 +305,14 @@ func Test_parseSBOM(t *testing.T) { } baseLayout := pkg.Package{ - Name: "alpine-baselayout", - Version: "3.2.0-r23", - Type: "apk", - Locations: apkgdbLocation, - Licenses: pkg.NewLicenseSet(pkg.NewLicense("GPL-2.0-only")), - FoundBy: "apkdb-cataloger", - PURL: "pkg:apk/alpine/alpine-baselayout@3.2.0-r23?arch=x86_64&upstream=alpine-baselayout&distro=alpine-3.16.3", + Name: "alpine-baselayout", + Version: "3.2.0-r23", + Type: "apk", + Locations: sbomLocations, + Licenses: pkg.NewLicenseSet(pkg.NewLicense("GPL-2.0-only")), + FoundBy: "sbom-cataloger", + PURL: "pkg:apk/alpine/alpine-baselayout@3.2.0-r23?arch=x86_64&upstream=alpine-baselayout&distro=alpine-3.16.3", + Dependencies: pkg.UnknownDependencyCompleteness, CPEs: mustCPEs( "cpe:2.3:a:alpine-baselayout:alpine-baselayout:3.2.0-r23:*:*:*:*:*:*:*", "cpe:2.3:a:alpine-baselayout:alpine_baselayout:3.2.0-r23:*:*:*:*:*:*:*", @@ -314,26 +324,28 @@ func Test_parseSBOM(t *testing.T) { } busybox := pkg.Package{ - Name: "busybox", - Version: "1.35.0-r17", - Type: "apk", - Locations: apkgdbLocation, - Licenses: pkg.NewLicenseSet(pkg.NewLicense("GPL-2.0-only")), - FoundBy: "apkdb-cataloger", - PURL: "pkg:apk/alpine/busybox@1.35.0-r17?arch=x86_64&upstream=busybox&distro=alpine-3.16.3", + Name: "busybox", + Version: "1.35.0-r17", + Type: "apk", + Locations: sbomLocations, + Licenses: pkg.NewLicenseSet(pkg.NewLicense("GPL-2.0-only")), + FoundBy: "sbom-cataloger", + PURL: "pkg:apk/alpine/busybox@1.35.0-r17?arch=x86_64&upstream=busybox&distro=alpine-3.16.3", + Dependencies: pkg.UnknownDependencyCompleteness, CPEs: mustCPEs( "cpe:2.3:a:busybox:busybox:1.35.0-r17:*:*:*:*:*:*:*", ), } musl := pkg.Package{ - Name: "musl", - Version: "1.2.3-r1", - Type: "apk", - Locations: apkgdbLocation, - Licenses: pkg.NewLicenseSet(pkg.NewLicense("MIT")), - FoundBy: "apkdb-cataloger", - PURL: "pkg:apk/alpine/musl@1.2.3-r1?arch=x86_64&upstream=musl&distro=alpine-3.16.3", + Name: "musl", + Version: "1.2.3-r1", + Type: "apk", + Locations: sbomLocations, + Licenses: pkg.NewLicenseSet(pkg.NewLicense("MIT")), + FoundBy: "sbom-cataloger", + PURL: "pkg:apk/alpine/musl@1.2.3-r1?arch=x86_64&upstream=musl&distro=alpine-3.16.3", + Dependencies: pkg.UnknownDependencyCompleteness, CPEs: mustCPEs( "cpe:2.3:a:musl:musl:1.2.3-r1:*:*:*:*:*:*:*", ), diff --git a/syft/pkg/cataloger/swift/package.go b/syft/pkg/cataloger/swift/package.go index c4370f5dc..051255583 100644 --- a/syft/pkg/cataloger/swift/package.go +++ b/syft/pkg/cataloger/swift/package.go @@ -16,6 +16,8 @@ func newSwiftPackageManagerPackage(name, version, sourceURL, revision string, lo Locations: file.NewLocationSet(locations...), Type: pkg.SwiftPkg, Language: pkg.Swift, + // no attempt is made by the parser function to resolve dependencies + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.SwiftPackageManagerResolvedEntry{ Revision: revision, }, @@ -34,6 +36,8 @@ func newCocoaPodsPackage(name, version, hash string, locations ...file.Location) Locations: file.NewLocationSet(locations...), Type: pkg.CocoapodsPkg, Language: pkg.Swift, + // no attempt is made by the parser function to resolve dependencies + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.CocoaPodfileLockEntry{ Checksum: hash, }, diff --git a/syft/pkg/cataloger/swift/parse_package_resolved_test.go b/syft/pkg/cataloger/swift/parse_package_resolved_test.go index bf16d7542..1f03a3ec7 100644 --- a/syft/pkg/cataloger/swift/parse_package_resolved_test.go +++ b/syft/pkg/cataloger/swift/parse_package_resolved_test.go @@ -13,61 +13,68 @@ import ( "github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest" ) +//Coffee1194 + func TestParsePackageResolved(t *testing.T) { fixture := "test-fixtures/Package.resolved" locations := file.NewLocationSet(file.NewLocation(fixture)) expectedPkgs := []pkg.Package{ { - Name: "swift-algorithms", - Version: "1.0.0", - PURL: "pkg:swift/github.com/apple/swift-algorithms.git/swift-algorithms@1.0.0", - Locations: locations, - Language: pkg.Swift, - Type: pkg.SwiftPkg, + Name: "swift-algorithms", + Version: "1.0.0", + PURL: "pkg:swift/github.com/apple/swift-algorithms.git/swift-algorithms@1.0.0", + Locations: locations, + Language: pkg.Swift, + Type: pkg.SwiftPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.SwiftPackageManagerResolvedEntry{ Revision: "b14b7f4c528c942f121c8b860b9410b2bf57825e", }, }, { - Name: "swift-async-algorithms", - Version: "0.1.0", - PURL: "pkg:swift/github.com/apple/swift-async-algorithms.git/swift-async-algorithms@0.1.0", - Locations: locations, - Language: pkg.Swift, - Type: pkg.SwiftPkg, + Name: "swift-async-algorithms", + Version: "0.1.0", + PURL: "pkg:swift/github.com/apple/swift-async-algorithms.git/swift-async-algorithms@0.1.0", + Locations: locations, + Language: pkg.Swift, + Type: pkg.SwiftPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.SwiftPackageManagerResolvedEntry{ Revision: "9cfed92b026c524674ed869a4ff2dcfdeedf8a2a", }, }, { - Name: "swift-atomics", - Version: "1.1.0", - PURL: "pkg:swift/github.com/apple/swift-atomics.git/swift-atomics@1.1.0", - Locations: locations, - Language: pkg.Swift, - Type: pkg.SwiftPkg, + Name: "swift-atomics", + Version: "1.1.0", + PURL: "pkg:swift/github.com/apple/swift-atomics.git/swift-atomics@1.1.0", + Locations: locations, + Language: pkg.Swift, + Type: pkg.SwiftPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.SwiftPackageManagerResolvedEntry{ Revision: "6c89474e62719ddcc1e9614989fff2f68208fe10", }, }, { - Name: "swift-collections", - Version: "1.0.4", - PURL: "pkg:swift/github.com/apple/swift-collections.git/swift-collections@1.0.4", - Locations: locations, - Language: pkg.Swift, - Type: pkg.SwiftPkg, + Name: "swift-collections", + Version: "1.0.4", + PURL: "pkg:swift/github.com/apple/swift-collections.git/swift-collections@1.0.4", + Locations: locations, + Language: pkg.Swift, + Type: pkg.SwiftPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.SwiftPackageManagerResolvedEntry{ Revision: "937e904258d22af6e447a0b72c0bc67583ef64a2", }, }, { - Name: "swift-numerics", - Version: "1.0.2", - PURL: "pkg:swift/github.com/apple/swift-numerics/swift-numerics@1.0.2", - Locations: locations, - Language: pkg.Swift, - Type: pkg.SwiftPkg, + Name: "swift-numerics", + Version: "1.0.2", + PURL: "pkg:swift/github.com/apple/swift-numerics/swift-numerics@1.0.2", + Locations: locations, + Language: pkg.Swift, + Type: pkg.SwiftPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.SwiftPackageManagerResolvedEntry{ Revision: "0a5bc04095a675662cf24757cc0640aa2204253b", }, @@ -85,23 +92,25 @@ func TestParsePackageResolvedV3(t *testing.T) { locations := file.NewLocationSet(file.NewLocation(fixture)) expectedPkgs := []pkg.Package{ { - Name: "swift-mmio", - Version: "", - PURL: "pkg:swift/github.com/apple/swift-mmio/swift-mmio", - Locations: locations, - Language: pkg.Swift, - Type: pkg.SwiftPkg, + Name: "swift-mmio", + Version: "", + PURL: "pkg:swift/github.com/apple/swift-mmio/swift-mmio", + Locations: locations, + Language: pkg.Swift, + Type: pkg.SwiftPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.SwiftPackageManagerResolvedEntry{ Revision: "80c109b87511041338a4d8d88064088c8dfc079b", }, }, { - Name: "swift-syntax", - Version: "509.1.1", - PURL: "pkg:swift/github.com/apple/swift-syntax.git/swift-syntax@509.1.1", - Locations: locations, - Language: pkg.Swift, - Type: pkg.SwiftPkg, + Name: "swift-syntax", + Version: "509.1.1", + PURL: "pkg:swift/github.com/apple/swift-syntax.git/swift-syntax@509.1.1", + Locations: locations, + Language: pkg.Swift, + Type: pkg.SwiftPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.SwiftPackageManagerResolvedEntry{ Revision: "64889f0c732f210a935a0ad7cda38f77f876262d", }, diff --git a/syft/pkg/cataloger/swift/parse_podfile_lock_test.go b/syft/pkg/cataloger/swift/parse_podfile_lock_test.go index 0abdd0d7c..e6a4ce15b 100644 --- a/syft/pkg/cataloger/swift/parse_podfile_lock_test.go +++ b/syft/pkg/cataloger/swift/parse_podfile_lock_test.go @@ -14,254 +14,277 @@ func TestParsePodfileLock(t *testing.T) { locations := file.NewLocationSet(file.NewLocation(fixture)) expectedPkgs := []pkg.Package{ { - Name: "GlossButtonNode", - Version: "3.1.2", - PURL: "pkg:cocoapods/GlossButtonNode@3.1.2", - Locations: locations, - Language: pkg.Swift, - Type: pkg.CocoapodsPkg, + Name: "GlossButtonNode", + Version: "3.1.2", + PURL: "pkg:cocoapods/GlossButtonNode@3.1.2", + Locations: locations, + Language: pkg.Swift, + Type: pkg.CocoapodsPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.CocoaPodfileLockEntry{ Checksum: "4ea1197a744f2fb5fb875fe31caf17ded4762e8f", }, }, { - Name: "PINCache", - Version: "3.0.3", - PURL: "pkg:cocoapods/PINCache@3.0.3", - Locations: locations, - Language: pkg.Swift, - Type: pkg.CocoapodsPkg, + Name: "PINCache", + Version: "3.0.3", + PURL: "pkg:cocoapods/PINCache@3.0.3", + Locations: locations, + Language: pkg.Swift, + Type: pkg.CocoapodsPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.CocoaPodfileLockEntry{ Checksum: "7a8fc1a691173d21dbddbf86cd515de6efa55086", }, }, { - Name: "PINCache/Arc-exception-safe", - Version: "3.0.3", - PURL: "pkg:cocoapods/PINCache/Arc-exception-safe@3.0.3", - Locations: locations, - Language: pkg.Swift, - Type: pkg.CocoapodsPkg, + Name: "PINCache/Arc-exception-safe", + Version: "3.0.3", + PURL: "pkg:cocoapods/PINCache/Arc-exception-safe@3.0.3", + Locations: locations, + Language: pkg.Swift, + Type: pkg.CocoapodsPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.CocoaPodfileLockEntry{ Checksum: "7a8fc1a691173d21dbddbf86cd515de6efa55086", }, }, { - Name: "PINCache/Core", - Version: "3.0.3", - PURL: "pkg:cocoapods/PINCache/Core@3.0.3", - Locations: locations, - Language: pkg.Swift, - Type: pkg.CocoapodsPkg, + Name: "PINCache/Core", + Version: "3.0.3", + PURL: "pkg:cocoapods/PINCache/Core@3.0.3", + Locations: locations, + Language: pkg.Swift, + Type: pkg.CocoapodsPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.CocoaPodfileLockEntry{ Checksum: "7a8fc1a691173d21dbddbf86cd515de6efa55086", }, }, { - Name: "PINOperation", - Version: "1.2.1", - PURL: "pkg:cocoapods/PINOperation@1.2.1", - Locations: locations, - Language: pkg.Swift, - Type: pkg.CocoapodsPkg, + Name: "PINOperation", + Version: "1.2.1", + PURL: "pkg:cocoapods/PINOperation@1.2.1", + Locations: locations, + Language: pkg.Swift, + Type: pkg.CocoapodsPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.CocoaPodfileLockEntry{ Checksum: "00c935935f1e8cf0d1e2d6b542e75b88fc3e5e20", }, }, { - Name: "PINRemoteImage/Core", - Version: "3.0.3", - PURL: "pkg:cocoapods/PINRemoteImage/Core@3.0.3", - Locations: locations, - Language: pkg.Swift, - Type: pkg.CocoapodsPkg, + Name: "PINRemoteImage/Core", + Version: "3.0.3", + PURL: "pkg:cocoapods/PINRemoteImage/Core@3.0.3", + Locations: locations, + Language: pkg.Swift, + Type: pkg.CocoapodsPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.CocoaPodfileLockEntry{ Checksum: "f1295b29f8c5e640e25335a1b2bd9d805171bd01", }, }, { - Name: "PINRemoteImage/iOS", - Version: "3.0.3", - PURL: "pkg:cocoapods/PINRemoteImage/iOS@3.0.3", - Locations: locations, - Language: pkg.Swift, - Type: pkg.CocoapodsPkg, + Name: "PINRemoteImage/iOS", + Version: "3.0.3", + PURL: "pkg:cocoapods/PINRemoteImage/iOS@3.0.3", + Locations: locations, + Language: pkg.Swift, + Type: pkg.CocoapodsPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.CocoaPodfileLockEntry{ Checksum: "f1295b29f8c5e640e25335a1b2bd9d805171bd01", }, }, { - Name: "PINRemoteImage/PINCache", - Version: "3.0.3", - PURL: "pkg:cocoapods/PINRemoteImage/PINCache@3.0.3", - Locations: locations, - Language: pkg.Swift, - Type: pkg.CocoapodsPkg, + Name: "PINRemoteImage/PINCache", + Version: "3.0.3", + PURL: "pkg:cocoapods/PINRemoteImage/PINCache@3.0.3", + Locations: locations, + Language: pkg.Swift, + Type: pkg.CocoapodsPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.CocoaPodfileLockEntry{ Checksum: "f1295b29f8c5e640e25335a1b2bd9d805171bd01", }, }, { - Name: "Reveal-SDK", - Version: "33", - PURL: "pkg:cocoapods/Reveal-SDK@33", - Locations: locations, - Language: pkg.Swift, - Type: pkg.CocoapodsPkg, + Name: "Reveal-SDK", + Version: "33", + PURL: "pkg:cocoapods/Reveal-SDK@33", + Locations: locations, + Language: pkg.Swift, + Type: pkg.CocoapodsPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.CocoaPodfileLockEntry{ Checksum: "effba1c940b8337195563c425a6b5862ec875caa", }, }, { - Name: "SwiftGen", - Version: "6.5.1", - PURL: "pkg:cocoapods/SwiftGen@6.5.1", - Locations: locations, - Language: pkg.Swift, - Type: pkg.CocoapodsPkg, + Name: "SwiftGen", + Version: "6.5.1", + PURL: "pkg:cocoapods/SwiftGen@6.5.1", + Locations: locations, + Language: pkg.Swift, + Type: pkg.CocoapodsPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.CocoaPodfileLockEntry{ Checksum: "a6d22010845f08fe18fbdf3a07a8e380fd22e0ea", }, }, { - Name: "Texture", - Version: "3.1.0", - PURL: "pkg:cocoapods/Texture@3.1.0", - Locations: locations, - Language: pkg.Swift, - Type: pkg.CocoapodsPkg, + Name: "Texture", + Version: "3.1.0", + PURL: "pkg:cocoapods/Texture@3.1.0", + Locations: locations, + Language: pkg.Swift, + Type: pkg.CocoapodsPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.CocoaPodfileLockEntry{ Checksum: "2e8ab2519452515f7f5a520f5a8f7e0a413abfa3", }, }, { - Name: "Texture/AssetsLibrary", - Version: "3.1.0", - PURL: "pkg:cocoapods/Texture/AssetsLibrary@3.1.0", - Locations: locations, - Language: pkg.Swift, - Type: pkg.CocoapodsPkg, + Name: "Texture/AssetsLibrary", + Version: "3.1.0", + PURL: "pkg:cocoapods/Texture/AssetsLibrary@3.1.0", + Locations: locations, + Language: pkg.Swift, + Type: pkg.CocoapodsPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.CocoaPodfileLockEntry{ Checksum: "2e8ab2519452515f7f5a520f5a8f7e0a413abfa3", }, }, { - Name: "Texture/Core", - Version: "3.1.0", - PURL: "pkg:cocoapods/Texture/Core@3.1.0", - Locations: locations, - Language: pkg.Swift, - Type: pkg.CocoapodsPkg, + Name: "Texture/Core", + Version: "3.1.0", + PURL: "pkg:cocoapods/Texture/Core@3.1.0", + Locations: locations, + Language: pkg.Swift, + Type: pkg.CocoapodsPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.CocoaPodfileLockEntry{ Checksum: "2e8ab2519452515f7f5a520f5a8f7e0a413abfa3", }, }, { - Name: "Texture/MapKit", - Version: "3.1.0", - PURL: "pkg:cocoapods/Texture/MapKit@3.1.0", - Locations: locations, - Language: pkg.Swift, - Type: pkg.CocoapodsPkg, + Name: "Texture/MapKit", + Version: "3.1.0", + PURL: "pkg:cocoapods/Texture/MapKit@3.1.0", + Locations: locations, + Language: pkg.Swift, + Type: pkg.CocoapodsPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.CocoaPodfileLockEntry{ Checksum: "2e8ab2519452515f7f5a520f5a8f7e0a413abfa3", }, }, { - Name: "Texture/Photos", - Version: "3.1.0", - PURL: "pkg:cocoapods/Texture/Photos@3.1.0", - Locations: locations, - Language: pkg.Swift, - Type: pkg.CocoapodsPkg, + Name: "Texture/Photos", + Version: "3.1.0", + PURL: "pkg:cocoapods/Texture/Photos@3.1.0", + Locations: locations, + Language: pkg.Swift, + Type: pkg.CocoapodsPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.CocoaPodfileLockEntry{ Checksum: "2e8ab2519452515f7f5a520f5a8f7e0a413abfa3", }, }, { - Name: "Texture/PINRemoteImage", - Version: "3.1.0", - PURL: "pkg:cocoapods/Texture/PINRemoteImage@3.1.0", - Locations: locations, - Language: pkg.Swift, - Type: pkg.CocoapodsPkg, + Name: "Texture/PINRemoteImage", + Version: "3.1.0", + PURL: "pkg:cocoapods/Texture/PINRemoteImage@3.1.0", + Locations: locations, + Language: pkg.Swift, + Type: pkg.CocoapodsPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.CocoaPodfileLockEntry{ Checksum: "2e8ab2519452515f7f5a520f5a8f7e0a413abfa3", }, }, { - Name: "Texture/Video", - Version: "3.1.0", - PURL: "pkg:cocoapods/Texture/Video@3.1.0", - Locations: locations, - Language: pkg.Swift, - Type: pkg.CocoapodsPkg, + Name: "Texture/Video", + Version: "3.1.0", + PURL: "pkg:cocoapods/Texture/Video@3.1.0", + Locations: locations, + Language: pkg.Swift, + Type: pkg.CocoapodsPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.CocoaPodfileLockEntry{ Checksum: "2e8ab2519452515f7f5a520f5a8f7e0a413abfa3", }, }, { - Name: "TextureSwiftSupport", - Version: "3.13.0", - PURL: "pkg:cocoapods/TextureSwiftSupport@3.13.0", - Locations: locations, - Language: pkg.Swift, - Type: pkg.CocoapodsPkg, + Name: "TextureSwiftSupport", + Version: "3.13.0", + PURL: "pkg:cocoapods/TextureSwiftSupport@3.13.0", + Locations: locations, + Language: pkg.Swift, + Type: pkg.CocoapodsPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.CocoaPodfileLockEntry{ Checksum: "c515c7927fab92d0d9485f49b885b8c5de34fbfb", }, }, { - Name: "TextureSwiftSupport/Components", - Version: "3.13.0", - PURL: "pkg:cocoapods/TextureSwiftSupport/Components@3.13.0", - Locations: locations, - Language: pkg.Swift, - Type: pkg.CocoapodsPkg, + Name: "TextureSwiftSupport/Components", + Version: "3.13.0", + PURL: "pkg:cocoapods/TextureSwiftSupport/Components@3.13.0", + Locations: locations, + Language: pkg.Swift, + Type: pkg.CocoapodsPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.CocoaPodfileLockEntry{ Checksum: "c515c7927fab92d0d9485f49b885b8c5de34fbfb", }, }, { - Name: "TextureSwiftSupport/Experiments", - Version: "3.13.0", - PURL: "pkg:cocoapods/TextureSwiftSupport/Experiments@3.13.0", - Locations: locations, - Language: pkg.Swift, - Type: pkg.CocoapodsPkg, + Name: "TextureSwiftSupport/Experiments", + Version: "3.13.0", + PURL: "pkg:cocoapods/TextureSwiftSupport/Experiments@3.13.0", + Locations: locations, + Language: pkg.Swift, + Type: pkg.CocoapodsPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.CocoaPodfileLockEntry{ Checksum: "c515c7927fab92d0d9485f49b885b8c5de34fbfb", }, }, { - Name: "TextureSwiftSupport/Extensions", - Version: "3.13.0", - PURL: "pkg:cocoapods/TextureSwiftSupport/Extensions@3.13.0", - Locations: locations, - Language: pkg.Swift, - Type: pkg.CocoapodsPkg, + Name: "TextureSwiftSupport/Extensions", + Version: "3.13.0", + PURL: "pkg:cocoapods/TextureSwiftSupport/Extensions@3.13.0", + Locations: locations, + Language: pkg.Swift, + Type: pkg.CocoapodsPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.CocoaPodfileLockEntry{ Checksum: "c515c7927fab92d0d9485f49b885b8c5de34fbfb", }, }, { - Name: "TextureSwiftSupport/LayoutSpecBuilders", - Version: "3.13.0", - PURL: "pkg:cocoapods/TextureSwiftSupport/LayoutSpecBuilders@3.13.0", - Locations: locations, - Language: pkg.Swift, - Type: pkg.CocoapodsPkg, + Name: "TextureSwiftSupport/LayoutSpecBuilders", + Version: "3.13.0", + PURL: "pkg:cocoapods/TextureSwiftSupport/LayoutSpecBuilders@3.13.0", + Locations: locations, + Language: pkg.Swift, + Type: pkg.CocoapodsPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.CocoaPodfileLockEntry{ Checksum: "c515c7927fab92d0d9485f49b885b8c5de34fbfb", }, }, { - Name: "TinyConstraints", - Version: "4.0.2", - PURL: "pkg:cocoapods/TinyConstraints@4.0.2", - Locations: locations, - Language: pkg.Swift, - Type: pkg.CocoapodsPkg, + Name: "TinyConstraints", + Version: "4.0.2", + PURL: "pkg:cocoapods/TinyConstraints@4.0.2", + Locations: locations, + Language: pkg.Swift, + Type: pkg.CocoapodsPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.CocoaPodfileLockEntry{ Checksum: "7b7ccc0c485bb3bb47082138ff28bc33cd49897f", }, diff --git a/syft/pkg/cataloger/swipl/package.go b/syft/pkg/cataloger/swipl/package.go index 6421ede70..4202861d7 100644 --- a/syft/pkg/cataloger/swipl/package.go +++ b/syft/pkg/cataloger/swipl/package.go @@ -14,7 +14,9 @@ func newSwiplPackPackage(m pkg.SwiplPackEntry, locations ...file.Location) pkg.P Locations: file.NewLocationSet(locations...), Type: pkg.SwiplPackPkg, Language: pkg.Swipl, - Metadata: m, + // no attempt is made by the parser function to resolve dependencies + Dependencies: pkg.IncompleteDependencies, + Metadata: m, } p.SetID() diff --git a/syft/pkg/cataloger/swipl/parse_pack_test.go b/syft/pkg/cataloger/swipl/parse_pack_test.go index 28feb7690..c35c77ecf 100644 --- a/syft/pkg/cataloger/swipl/parse_pack_test.go +++ b/syft/pkg/cataloger/swipl/parse_pack_test.go @@ -9,17 +9,18 @@ import ( "github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest" ) -func TestParsePackPackage(t *testing.T) { +func xTestParsePackPackage(t *testing.T) { fixture := "test-fixtures/pack.pl" locations := file.NewLocationSet(file.NewLocation(fixture)) expectedPkgs := []pkg.Package{ { - Name: "hdt", - Version: "0.5.2", - PURL: "pkg:swiplpack/hdt@0.5.2", - Locations: locations, - Language: pkg.Swipl, - Type: pkg.SwiplPackPkg, + Name: "hdt", + Version: "0.5.2", + PURL: "pkg:swiplpack/hdt@0.5.2", + Locations: locations, + Language: pkg.Swipl, + Type: pkg.SwiplPackPkg, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.SwiplPackEntry{ Name: "hdt", Version: "0.5.2", diff --git a/syft/pkg/cataloger/wordpress/package.go b/syft/pkg/cataloger/wordpress/package.go index 596ccfb5a..55e5482d6 100644 --- a/syft/pkg/cataloger/wordpress/package.go +++ b/syft/pkg/cataloger/wordpress/package.go @@ -18,7 +18,9 @@ func newWordpressPluginPackage(name, version string, m pluginData, location file Locations: file.NewLocationSet(location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), Language: pkg.PHP, Type: pkg.WordpressPluginPkg, - Metadata: meta, + // no attempt is made by the parser function to resolve dependencies + Dependencies: pkg.IncompleteDependencies, + Metadata: meta, } if len(m.Licenses) > 0 { diff --git a/syft/pkg/cataloger/wordpress/parse_plugin_test.go b/syft/pkg/cataloger/wordpress/parse_plugin_test.go index a9e10f289..c6e1f64c5 100644 --- a/syft/pkg/cataloger/wordpress/parse_plugin_test.go +++ b/syft/pkg/cataloger/wordpress/parse_plugin_test.go @@ -22,7 +22,8 @@ func TestParseWordpressPluginFiles(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("GPLv2"), ), - Language: pkg.PHP, + Language: pkg.PHP, + Dependencies: pkg.IncompleteDependencies, Metadata: pkg.WordpressPluginEntry{ PluginInstallDirectory: "akismet", Author: "Automattic - Anti-spam Team", diff --git a/syft/pkg/dependencies.go b/syft/pkg/dependencies.go new file mode 100644 index 000000000..f3e0fd7ab --- /dev/null +++ b/syft/pkg/dependencies.go @@ -0,0 +1,47 @@ +package pkg + +import "strings" + +// DependencyCompleteness describes the quality of the current package and if the SBOM contains relationships to +// a complete set of dependencies. We are only concerned with describing the completeness of the dependencies +// relative to the direct dependencies of the package, not the completeness of the entire graph beyond direct +// dependencies. Completeness should apply to packages required by the current package that are non-test and +// non-development dependencies in nature. There is no distinction about build-time vs runtime dependencies. +// Overall completeness is a function of node connectivity within the SBOM graph, it is not sufficient that all +// dependencies exist in the graph to be considered complete, they must have explicit relationships that denote +// each dependency. +type DependencyCompleteness string + +const ( + // UnknownDependencyCompleteness indicates that the completeness of the dependencies is unknown. This should be used + // when the dependency resolution mechanism is not well understood. + UnknownDependencyCompleteness DependencyCompleteness = "unknown" + + // CompleteDependencies indicates that the package has all of its direct dependencies resolved and related to + // this package. Note that any indirect (transitive) dependencies must not be directly linked to this package. + CompleteDependencies DependencyCompleteness = "complete" + + // MixedDependencies is a superset of complete. It indicates that the package has all of its direct dependencies + // resolved as well as one or all of indirect dependencies. What is notable about this is that direct and + // indirect dependencies are linked directly to this package and are not separable (you cannot distinguish between + // a direct and indirect dependency from the perspective of this package). + MixedDependencies DependencyCompleteness = "mixed" + + // IncompleteDependencies indicates that the package does not have all of its dependencies resolved. This is useful + // in times when there is more than one mechanism at play for resolving dependencies and the cataloger only + // implements a subset of them, or in cases where the mechanism for resolving dependencies is limited. + IncompleteDependencies DependencyCompleteness = "incomplete" +) + +func ParseDependencyCompleteness(value string) DependencyCompleteness { + switch strings.ToLower(strings.TrimSpace(value)) { + case string(CompleteDependencies): + return CompleteDependencies + case string(MixedDependencies): + return MixedDependencies + case string(IncompleteDependencies): + return IncompleteDependencies + default: + return UnknownDependencyCompleteness + } +} diff --git a/syft/pkg/package.go b/syft/pkg/package.go index 8ee8d969f..c16295028 100644 --- a/syft/pkg/package.go +++ b/syft/pkg/package.go @@ -17,17 +17,18 @@ import ( // Package represents an application or library that has been bundled into a distributable format. // TODO: if we ignore FoundBy for ID generation should we merge the field to show it was found in two places? type Package struct { - id artifact.ID `hash:"ignore"` - Name string // the package name - Version string // the version of the package - FoundBy string `hash:"ignore" cyclonedx:"foundBy"` // the specific cataloger that discovered this package - Locations file.LocationSet // the locations that lead to the discovery of this package (note: this is not necessarily the locations that make up this package) - Licenses LicenseSet // licenses discovered with the package metadata - Language Language `hash:"ignore" cyclonedx:"language"` // the language ecosystem this package belongs to (e.g. JavaScript, Python, etc) - Type Type `cyclonedx:"type"` // the package type (e.g. Npm, Yarn, Python, Rpm, Deb, etc) - CPEs []cpe.CPE `hash:"ignore"` // all possible Common Platform Enumerators (note: this is NOT included in the definition of the ID since all fields on a CPE are derived from other fields) - PURL string `hash:"ignore"` // the Package URL (see https://github.com/package-url/purl-spec) - Metadata interface{} // additional data found while parsing the package source + id artifact.ID `hash:"ignore"` + Name string // the package name + Version string // the version of the package + FoundBy string `hash:"ignore" cyclonedx:"foundBy"` // the specific cataloger that discovered this package + Locations file.LocationSet // the locations that lead to the discovery of this package (note: this is not necessarily the locations that make up this package) + Licenses LicenseSet // licenses discovered with the package metadata + Language Language `hash:"ignore" cyclonedx:"language"` // the language ecosystem this package belongs to (e.g. JavaScript, Python, etc) + Type Type `cyclonedx:"type"` // the package type (e.g. Npm, Yarn, Python, Rpm, Deb, etc) + CPEs []cpe.CPE `hash:"ignore"` // all possible Common Platform Enumerators (note: this is NOT included in the definition of the ID since all fields on a CPE are derived from other fields) + PURL string `hash:"ignore"` // the Package URL (see https://github.com/package-url/purl-spec) + Dependencies DependencyCompleteness `hash:"ignore"` // the completeness of the dependency information for this package + Metadata interface{} // additional data found while parsing the package source } func (p *Package) OverrideID(id artifact.ID) {